File indexing completed on 2025-01-05 03:59:25
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( QLatin1String("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( QLatin1String("marble/navigation/navigational_arrows") ); 0035 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_hover_bottom") ); 0036 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_hover_left") ); 0037 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_hover_right") ); 0038 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_hover_top") ); 0039 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_press_bottom") ); 0040 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_press_left") ); 0041 QPixmapCache::remove( QLatin1String("marble/navigation/navigational_arrows_press_right") ); 0042 QPixmapCache::remove( QLatin1String("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 = QLatin1String("marble/navigation/navigational_arrows"); 0073 break; 0074 case Qt::UpArrow: 0075 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_press_top"); 0076 m_marbleWidget->moveUp(Marble::Linear); 0077 break; 0078 case Qt::DownArrow: 0079 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_press_bottom"); 0080 m_marbleWidget->moveDown(Marble::Linear); 0081 break; 0082 case Qt::LeftArrow: 0083 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_press_left"); 0084 m_marbleWidget->moveLeft(Marble::Linear); 0085 break; 0086 case Qt::RightArrow: 0087 m_imagePath = QLatin1String("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 = QLatin1String("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 = QLatin1String("marble/navigation/navigational_arrows"); 0154 break; 0155 case Qt::UpArrow: 0156 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_hover_top"); 0157 m_arrowPressed = Qt::UpArrow; 0158 break; 0159 case Qt::DownArrow: 0160 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_hover_bottom"); 0161 m_arrowPressed = Qt::DownArrow; 0162 break; 0163 case Qt::LeftArrow: 0164 m_imagePath = QLatin1String("marble/navigation/navigational_arrows_hover_left"); 0165 m_arrowPressed = Qt::LeftArrow; 0166 break; 0167 case Qt::RightArrow: 0168 m_imagePath = QLatin1String("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 Q_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"