File indexing completed on 2025-01-05 03:59:17
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 // Qt 0011 #include <QMouseEvent> 0012 0013 // Marble 0014 #include "MarbleWidget.h" 0015 0016 #include "digikam_debug.h" 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 }