File indexing completed on 2024-05-05 03:50:46

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2013 Mohammed Nafees <nafees.technocool@gmail.com>
0004 //
0005 
0006 #include "ArrowDiscWidget.h"
0007 
0008 #include "MarbleWidget.h"
0009 
0010 #include <qmath.h>
0011 #include <QPainter>
0012 #include <QMouseEvent>
0013 #include <QPixmapCache>
0014 
0015 namespace Marble
0016 {
0017 
0018 ArrowDiscWidget::ArrowDiscWidget( QWidget *parent ) :
0019     QWidget( parent ),
0020     m_arrowPressed( Qt::NoArrow ),
0021     m_repetitions( 0 ),
0022     m_marbleWidget( nullptr ),
0023     m_imagePath( "marble/navigation/navigational_arrows" )
0024 {
0025     setMouseTracking( true );
0026 
0027     m_initialPressTimer.setSingleShot( true );
0028     connect( &m_initialPressTimer, SIGNAL(timeout()), SLOT(startPressRepeat()) );
0029     connect( &m_repeatPressTimer, SIGNAL(timeout()), SLOT(repeatPress()) );
0030 }
0031 
0032 ArrowDiscWidget::~ArrowDiscWidget()
0033 {
0034     QPixmapCache::remove( "marble/navigation/navigational_arrows" );
0035     QPixmapCache::remove( "marble/navigation/navigational_arrows_hover_bottom" );
0036     QPixmapCache::remove( "marble/navigation/navigational_arrows_hover_left" );
0037     QPixmapCache::remove( "marble/navigation/navigational_arrows_hover_right" );
0038     QPixmapCache::remove( "marble/navigation/navigational_arrows_hover_top" );
0039     QPixmapCache::remove( "marble/navigation/navigational_arrows_press_bottom" );
0040     QPixmapCache::remove( "marble/navigation/navigational_arrows_press_left" );
0041     QPixmapCache::remove( "marble/navigation/navigational_arrows_press_right" );
0042     QPixmapCache::remove( "marble/navigation/navigational_arrows_press_top" );
0043 }
0044 
0045 void ArrowDiscWidget::setMarbleWidget( MarbleWidget *marbleWidget )
0046 {
0047     m_marbleWidget = marbleWidget;
0048 }
0049 
0050 QPixmap ArrowDiscWidget::pixmap( const QString &id )
0051 {
0052     QPixmap result;
0053     if ( !QPixmapCache::find( id, &result ) ) {
0054         result = QPixmap(QLatin1String(":/") + id + QLatin1String(".png"));
0055         QPixmapCache::insert( id, result );
0056     }
0057     return result;
0058 }
0059 
0060 void ArrowDiscWidget::mousePressEvent( QMouseEvent *mouseEvent )
0061 {
0062     if ( mouseEvent->button() == Qt::LeftButton ) {
0063 
0064         if ( !m_initialPressTimer.isActive() && !m_repeatPressTimer.isActive() ) {
0065             m_repetitions = 0;
0066             m_initialPressTimer.start( 300 );
0067         }
0068 
0069         m_arrowPressed = arrowUnderMouse( mouseEvent->pos() );
0070         switch ( m_arrowPressed ) {
0071         case Qt::NoArrow:
0072             m_imagePath = "marble/navigation/navigational_arrows";
0073             break;
0074         case Qt::UpArrow:
0075             m_imagePath = "marble/navigation/navigational_arrows_press_top";
0076             m_marbleWidget->moveUp(Marble::Linear);
0077             break;
0078         case Qt::DownArrow:
0079             m_imagePath = "marble/navigation/navigational_arrows_press_bottom";
0080             m_marbleWidget->moveDown(Marble::Linear);
0081             break;
0082         case Qt::LeftArrow:
0083             m_imagePath = "marble/navigation/navigational_arrows_press_left";
0084             m_marbleWidget->moveLeft(Marble::Linear);
0085             break;
0086         case Qt::RightArrow:
0087             m_imagePath = "marble/navigation/navigational_arrows_press_right";
0088             m_marbleWidget->moveRight(Marble::Linear);
0089             break;
0090         }
0091     }
0092 
0093     repaint();
0094 }
0095 
0096 void ArrowDiscWidget::mouseReleaseEvent( QMouseEvent *mouseEvent )
0097 {
0098     m_initialPressTimer.stop();
0099     m_repeatPressTimer.stop();
0100     mouseMoveEvent( mouseEvent );
0101 }
0102 
0103 void ArrowDiscWidget::leaveEvent( QEvent* )
0104 {
0105     if (m_imagePath != QLatin1String("marble/navigation/navigational_arrows")) {
0106         m_imagePath = "marble/navigation/navigational_arrows";
0107         repaint();
0108     }
0109 
0110     m_initialPressTimer.stop();
0111     m_repeatPressTimer.stop();
0112 }
0113 
0114 void ArrowDiscWidget::startPressRepeat()
0115 {
0116     repeatPress();
0117 
0118     if ( m_arrowPressed != Qt::NoArrow ) {
0119         m_repeatPressTimer.start( 100 );
0120     }
0121 }
0122 
0123 void ArrowDiscWidget::repeatPress()
0124 {
0125     if ( m_repetitions <= 200 ) {
0126         ++m_repetitions;
0127         switch ( m_arrowPressed ) {
0128         case Qt::NoArrow:
0129             break;
0130         case Qt::UpArrow:
0131             m_marbleWidget->moveUp();
0132             break;
0133         case Qt::DownArrow:
0134             m_marbleWidget->moveDown();
0135             break;
0136         case Qt::LeftArrow:
0137             m_marbleWidget->moveLeft();
0138             break;
0139         case Qt::RightArrow:
0140             m_marbleWidget->moveRight();
0141             break;
0142         }
0143     } else {
0144         m_repeatPressTimer.stop();
0145     }
0146 }
0147 
0148 void ArrowDiscWidget::mouseMoveEvent( QMouseEvent *mouseEvent )
0149 {
0150     QString const oldPath = m_imagePath;
0151     switch ( arrowUnderMouse( mouseEvent->pos() ) ) {
0152     case Qt::NoArrow:
0153         m_imagePath = "marble/navigation/navigational_arrows";
0154         break;
0155     case Qt::UpArrow:
0156         m_imagePath = "marble/navigation/navigational_arrows_hover_top";
0157         m_arrowPressed = Qt::UpArrow;
0158         break;
0159     case Qt::DownArrow:
0160         m_imagePath = "marble/navigation/navigational_arrows_hover_bottom";
0161         m_arrowPressed = Qt::DownArrow;
0162         break;
0163     case Qt::LeftArrow:
0164         m_imagePath = "marble/navigation/navigational_arrows_hover_left";
0165         m_arrowPressed = Qt::LeftArrow;
0166         break;
0167     case Qt::RightArrow:
0168         m_imagePath = "marble/navigation/navigational_arrows_hover_right";
0169         m_arrowPressed = Qt::RightArrow;
0170         break;
0171     }
0172 
0173     if ( m_imagePath != oldPath ) {
0174         repaint();
0175     }
0176 }
0177 
0178 void ArrowDiscWidget::repaint()
0179 {
0180     emit repaintNeeded();
0181 }
0182 
0183 Qt::ArrowType ArrowDiscWidget::arrowUnderMouse(const QPoint &position) const
0184 {
0185     const int min_radius_pow2 = 5*5;
0186     const int max_radius_pow2 = 28*28;
0187 
0188     // mouse coordinates relative to widget topleft
0189     int mx = position.x();
0190     int my = position.y();
0191 
0192     // center coordinates relative to widget topleft
0193     int cx = width()/2;
0194     int cy = height()/2;
0195 
0196     int px = mx - cx;
0197     int py = my - cy;
0198 
0199     int const distance_pow2 = px*px + py*py;
0200 
0201     if ( distance_pow2 >= min_radius_pow2 && distance_pow2 <= max_radius_pow2 ) {
0202         int const angle = int( qAtan2( py, px ) * RAD2DEG );
0203         Q_ASSERT( -180 <= angle && angle <= 180 );
0204 
0205         if ( angle >= 135 || angle < -135 ) {
0206             return Qt::LeftArrow;
0207         } else if ( angle < -45 ) {
0208             return Qt::UpArrow;
0209         } else if ( angle < 45 ) {
0210             return Qt::RightArrow;
0211         } else {
0212             return Qt::DownArrow;
0213         }
0214     }
0215 
0216     return Qt::NoArrow;
0217 }
0218 
0219 void ArrowDiscWidget::paintEvent( QPaintEvent * )
0220 {
0221     Q_ASSERT( !pixmap( m_imagePath ).isNull() );
0222     QPainter painter( this );
0223     painter.drawPixmap( 0, 0, pixmap( m_imagePath ) );
0224     painter.end();
0225 }
0226 
0227 }
0228 
0229 #include "moc_ArrowDiscWidget.cpp"