File indexing completed on 2024-05-05 03:49:48

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2009-2010 Bastian Holst <bastianholst@gmx.de>
0004 //
0005 
0006 // Self
0007 #include "ScreenGraphicsItem.h"
0008 #include "ScreenGraphicsItem_p.h"
0009 
0010 // Marble
0011 #include "MarbleDebug.h"
0012 #include "MarbleWidget.h"
0013 
0014 // Qt
0015 #include <QMouseEvent>
0016 
0017 
0018 using namespace Marble;
0019 
0020 ScreenGraphicsItem::ScreenGraphicsItem( MarbleGraphicsItem *parent )
0021     : MarbleGraphicsItem( new ScreenGraphicsItemPrivate( this, parent ) )
0022 {
0023 }
0024 
0025 ScreenGraphicsItem::ScreenGraphicsItem(ScreenGraphicsItemPrivate *dd)
0026     : MarbleGraphicsItem(dd)
0027 {
0028 }
0029 
0030 ScreenGraphicsItem::~ScreenGraphicsItem()
0031 {
0032 }
0033 
0034 QPointF ScreenGraphicsItem::position() const
0035 {
0036     Q_D(const ScreenGraphicsItem);
0037     return d->m_position;
0038 }
0039 
0040 void ScreenGraphicsItem::setPosition( const QPointF& position )
0041 {
0042     Q_D(ScreenGraphicsItem);
0043     d->m_position = position;
0044 }
0045 
0046 QPointF ScreenGraphicsItem::positivePosition() const
0047 {
0048     Q_D(const ScreenGraphicsItem);
0049     return d->positivePosition();
0050 }
0051 
0052 QVector<QPointF> ScreenGraphicsItem::absolutePositions() const
0053 {
0054     Q_D(const ScreenGraphicsItem);
0055     return d->absolutePositions();
0056 }
0057 
0058 ScreenGraphicsItem::GraphicsItemFlags ScreenGraphicsItem::flags() const
0059 {
0060     Q_D(const ScreenGraphicsItem);
0061     return d->m_flags;
0062 }
0063 
0064 void ScreenGraphicsItem::setFlags( ScreenGraphicsItem::GraphicsItemFlags flags )
0065 {
0066     Q_D(ScreenGraphicsItem);
0067     d->m_flags = flags;
0068 }
0069 
0070 bool ScreenGraphicsItem::eventFilter( QObject *object, QEvent *e )
0071 {
0072     MarbleWidget *widget = dynamic_cast<MarbleWidget*>(object);
0073     if ( !widget ) {
0074         return MarbleGraphicsItem::eventFilter( object, e );
0075     }
0076 
0077     Q_D(ScreenGraphicsItem);
0078     if (!d->m_floatItemMoving) {
0079         if ( MarbleGraphicsItem::eventFilter( object, e ) ) {
0080             return true;
0081         }
0082 
0083         if (!visible() || !d->isMovable()) {
0084             return false;
0085         }
0086         
0087         if ( e->type() == QEvent::MouseMove ) {
0088             return false;
0089         }
0090         
0091         // Move ScreenGraphicsItem
0092         if ( e->type() == QEvent::MouseButtonPress )
0093         {
0094             QMouseEvent *event = static_cast<QMouseEvent*>(e);
0095 
0096             // Click and move above a float item triggers moving the float item
0097             if ( contains( event->pos() ) ) {
0098                 if ( event->button() == Qt::LeftButton ) {
0099                     d->m_floatItemMoveStartPos = event->pos();
0100                     d->m_floatItemMoving = true;
0101                     return true;
0102                 }
0103             }
0104         }
0105         
0106         return false;
0107     }
0108     else {
0109         // Move ScreenGraphicsItem
0110         if ( e->type() == QEvent::MouseMove
0111             || e->type() == QEvent::MouseButtonPress
0112             || e->type() == QEvent::MouseButtonRelease )
0113         {
0114             QMouseEvent *event = static_cast<QMouseEvent*>( e );
0115             // The rect the item was painted on before. We add one pixel as antialiasing could
0116             // result into painting on these pixels to.
0117             QRectF floatItemRect = QRectF( positivePosition() - QPoint( 1, 1 ),
0118                                            size() + QSize( 2, 2 ) );
0119 
0120             if ( e->type() == QEvent::MouseMove && event->buttons() & Qt::LeftButton ) {
0121                     const QPoint &point = event->pos();
0122                     QPointF position = positivePosition();
0123                     qreal newX = qMax<qreal>(0, position.x() + point.x() - d->m_floatItemMoveStartPos.x());
0124                     qreal newY = qMax<qreal>(0, position.y() + point.y() - d->m_floatItemMoveStartPos.y());
0125 
0126                     // docking behavior
0127                     const qreal dockArea = 60.0; // Alignment area width/height
0128                     const qreal dockJump = 30.0; // Alignment indicator jump size
0129                     if ( widget->width()-size().width()-newX < dockArea ) {
0130                         newX = qMin( qreal( -1.0 ), size().width() + newX-widget->width() );
0131                         if (d->m_floatItemMoveStartPos.x() < event->pos().x()) {
0132                             // Indicate change to right alignment with a short jump
0133                             newX = qMax( newX, -(dockArea-dockJump) );
0134                         }
0135                     }
0136                     if ( widget->height()-size().height()-newY < dockArea ) {
0137                         newY = qMin( qreal( -1.0 ), size().height() + newY-widget->height() );
0138                         if (d->m_floatItemMoveStartPos.y() < event->pos().y()) {
0139                         // Indicate change to bottom alignment with a short jump
0140                         newY = qMax( newY, -( dockArea - dockJump ) );
0141                         }
0142                     }
0143 
0144                     setPosition( QPointF( newX,newY ) );
0145                     // The rect the item will be painted on now. We add one pixel as
0146                     // antialiasing could result into painting on these pixels to.
0147                     QRect newFloatItemRect = QRectF( positivePosition() - QPoint( 1, 1 ),
0148                                                      size() + QSize( 2, 2 ) ).toRect();
0149                     d->m_floatItemMoveStartPos = event->pos();
0150                     QRegion dirtyRegion( floatItemRect.toRect() );
0151                     dirtyRegion = dirtyRegion.united( newFloatItemRect );
0152 
0153                     widget->setAttribute( Qt::WA_NoSystemBackground,  false );
0154                     widget->update(dirtyRegion);
0155                     widget->setAttribute( Qt::WA_NoSystemBackground, widget->viewport()->mapCoversViewport() );
0156                     return true;
0157             }
0158 
0159             if ( e->type() == QEvent::MouseButtonRelease ) {
0160                 d->m_floatItemMoving = false;
0161             }
0162 
0163             // Use a special cursor as long as the item is moved
0164             if (d->m_floatItemMoving) {
0165                 widget->setCursor(QCursor(Qt::SizeAllCursor));
0166                 return true;
0167             }
0168         }
0169         
0170         return MarbleGraphicsItem::eventFilter( object, e );
0171     }
0172 }