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 }