File indexing completed on 2024-05-05 03:49:48
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de> 0004 // 0005 0006 // Self 0007 #include "WidgetGraphicsItem.h" 0008 #include "WidgetGraphicsItem_p.h" 0009 0010 // Marble 0011 #include "MarbleWidget.h" 0012 #include "MarbleDebug.h" 0013 0014 // Qt 0015 #include <QApplication> 0016 #include <QMouseEvent> 0017 #include <QPainter> 0018 #include <QWidget> 0019 0020 using namespace Marble; 0021 0022 WidgetGraphicsItemPrivate::WidgetGraphicsItemPrivate(WidgetGraphicsItem *widgetGraphicsItem, 0023 MarbleGraphicsItem *parent) 0024 : ScreenGraphicsItemPrivate(widgetGraphicsItem, parent), 0025 m_widget(nullptr), m_marbleWidget(nullptr), m_activeWidget( nullptr ) 0026 { 0027 // nothing to do 0028 } 0029 0030 WidgetGraphicsItemPrivate::~WidgetGraphicsItemPrivate() 0031 { 0032 delete m_widget; 0033 } 0034 0035 WidgetGraphicsItem::WidgetGraphicsItem( MarbleGraphicsItem *parent ) 0036 : ScreenGraphicsItem(new WidgetGraphicsItemPrivate(this, parent)) 0037 { 0038 } 0039 0040 WidgetGraphicsItem::~WidgetGraphicsItem() 0041 { 0042 } 0043 0044 void WidgetGraphicsItem::setWidget(QWidget *widget) 0045 { 0046 Q_D(WidgetGraphicsItem); 0047 d->m_widget = widget; 0048 0049 QSize size = widget->sizeHint().expandedTo( widget->size() ); 0050 size = size.expandedTo( widget->minimumSize() ); 0051 size = size.boundedTo( widget->maximumSize() ); 0052 setSize( size ); 0053 widget->resize( size ); 0054 } 0055 0056 QWidget *WidgetGraphicsItem::widget() const 0057 { 0058 Q_D(const WidgetGraphicsItem); 0059 return d->m_widget; 0060 } 0061 0062 void WidgetGraphicsItem::paint( QPainter *painter ) 0063 { 0064 Q_D(WidgetGraphicsItem); 0065 if( d->m_widget == nullptr ) 0066 return; 0067 0068 // Paint widget without a background 0069 d->m_widget->render( painter, QPoint( 0, 0 ), QRegion(), QWidget::RenderFlags( QWidget::DrawChildren) ); 0070 } 0071 0072 bool WidgetGraphicsItem::eventFilter( QObject *object, QEvent *e ) 0073 { 0074 Q_D(WidgetGraphicsItem); 0075 if ( !visible() || d->m_widget == nullptr ) { 0076 return false; 0077 } 0078 0079 MarbleWidget *widget = dynamic_cast<MarbleWidget*> (object); 0080 if ( !widget ) { 0081 return ScreenGraphicsItem::eventFilter(object, e); 0082 } 0083 0084 if ( d->m_marbleWidget != widget ) { 0085 // Delayed initialization 0086 d->m_marbleWidget = widget; 0087 } 0088 0089 Q_ASSERT(d->m_marbleWidget); 0090 0091 if ( e->type() == QEvent::MouseButtonDblClick 0092 || e->type() == QEvent::MouseMove 0093 || e->type() == QEvent::MouseButtonPress 0094 || e->type() == QEvent::MouseButtonRelease ) 0095 { 0096 // Mouse events are forwarded to the underlying widget 0097 QMouseEvent *event = static_cast<QMouseEvent*> ( e ); 0098 0099 const QVector<QPointF> widgetPositions = absolutePositions(); 0100 QRectF widgetItemRect; 0101 QPoint shiftedPos; 0102 QVector<QPointF>::ConstIterator it = widgetPositions.begin(); 0103 bool foundRightPosition = false; 0104 for(; !foundRightPosition && it != widgetPositions.end(); ++it ) { 0105 widgetItemRect = QRectF( *it, size() ); 0106 0107 if ( widgetItemRect.contains( event->pos() ) ) { 0108 foundRightPosition = true; 0109 shiftedPos = event->pos() - widgetItemRect.topLeft().toPoint(); 0110 } 0111 } 0112 0113 if ( foundRightPosition ) { 0114 QWidget *child = d->m_widget->childAt( shiftedPos ); 0115 0116 if ( d->m_activeWidget && d->m_activeWidget != child ) { 0117 QEvent leaveEvent( QEvent::Leave ); 0118 QApplication::sendEvent( d->m_activeWidget, &leaveEvent ); 0119 } 0120 0121 if ( child && d->m_activeWidget != child ) { 0122 QEvent enterEvent( QEvent::Enter ); 0123 QApplication::sendEvent( child, &enterEvent ); 0124 } 0125 d->m_activeWidget = child; 0126 0127 if ( child ) { 0128 shiftedPos -= child->pos(); // transform to children's coordinates 0129 QMouseEvent shiftedEvent = QMouseEvent( e->type(), shiftedPos, 0130 event->globalPos(), event->button(), event->buttons(), 0131 event->modifiers() ); 0132 if ( QApplication::sendEvent( child, &shiftedEvent ) ) { 0133 d->m_marbleWidget->setCursor( d->m_widget->cursor() ); 0134 return true; 0135 } 0136 } 0137 } else { 0138 if ( d->m_activeWidget ) { 0139 QEvent leaveEvent( QEvent::Leave ); 0140 QApplication::sendEvent( d->m_activeWidget, &leaveEvent ); 0141 d->m_activeWidget = nullptr; 0142 } 0143 } 0144 } 0145 0146 return ScreenGraphicsItem::eventFilter(object, e); 0147 }