File indexing completed on 2025-01-05 03:59:17

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