File indexing completed on 2024-12-01 09:41:29
0001 /* 0002 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 //This file contains Event handlers for the SkyMap class. 0008 0009 #include "skymap.h" 0010 0011 #include "ksplanetbase.h" 0012 #include "kspopupmenu.h" 0013 #include "kstars.h" 0014 #include "observinglist.h" 0015 #include "Options.h" 0016 #include "skyglpainter.h" 0017 #include "skyqpainter.h" 0018 #include "printing/simplefovexporter.h" 0019 #include "skycomponents/skylabeler.h" 0020 #include "skycomponents/skymapcomposite.h" 0021 #include "skycomponents/starcomponent.h" 0022 #include "skycomponents/mosaiccomponent.h" 0023 #ifdef HAVE_INDI 0024 #include "skyobjects/mosaictiles.h" 0025 #endif 0026 #include "widgets/infoboxwidget.h" 0027 0028 #include <QGestureEvent> 0029 #include <QStatusBar> 0030 #include <QToolTip> 0031 0032 void SkyMap::resizeEvent(QResizeEvent *) 0033 { 0034 computeSkymap = true; // skymap must be new computed 0035 0036 //FIXME: No equivalent for this line in Qt4 ?? 0037 // if ( testWState( Qt::WState_AutoMask ) ) updateMask(); 0038 0039 // Resize the widget that draws the sky map. 0040 // FIXME: The resize event doesn't pass to children. Any better way of doing this? 0041 m_SkyMapDraw->resize(size()); 0042 0043 // Resize infoboxes container. 0044 // FIXME: this is not really pretty. Maybe there are some better way to this??? 0045 m_iboxes->resize(size()); 0046 } 0047 0048 void SkyMap::keyPressEvent(QKeyEvent *e) 0049 { 0050 bool arrowKeyPressed(false); 0051 bool shiftPressed(false); 0052 float step = 1.0; 0053 if (e->modifiers() & Qt::ShiftModifier) 0054 { 0055 step = 10.0; 0056 shiftPressed = true; 0057 } 0058 0059 //If the DBus resume key is not empty, then DBus processing is 0060 //paused while we wait for a keypress 0061 if (!data->resumeKey.isEmpty() && QKeySequence(e->key()) == data->resumeKey) 0062 { 0063 //The resumeKey was pressed. Signal that it was pressed by 0064 //resetting it to empty; this will break the loop in 0065 //KStars::waitForKey() 0066 data->resumeKey = QKeySequence(); 0067 return; 0068 } 0069 0070 if (m_previewLegend) 0071 { 0072 slotCancelLegendPreviewMode(); 0073 } 0074 0075 switch (e->key()) 0076 { 0077 case Qt::Key_Left: 0078 if (Options::useAltAz()) 0079 { 0080 focus()->setAz(dms(focus()->az().Degrees() - step * MINZOOM / Options::zoomFactor()).reduce()); 0081 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); 0082 } 0083 else 0084 { 0085 focus()->setRA(focus()->ra().Hours() + 0.05 * step * MINZOOM / Options::zoomFactor()); 0086 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0087 } 0088 0089 arrowKeyPressed = true; 0090 slewing = true; 0091 break; 0092 0093 case Qt::Key_Right: 0094 if (Options::useAltAz()) 0095 { 0096 focus()->setAz(dms(focus()->az().Degrees() + step * MINZOOM / Options::zoomFactor()).reduce()); 0097 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); 0098 } 0099 else 0100 { 0101 focus()->setRA(focus()->ra().Hours() - 0.05 * step * MINZOOM / Options::zoomFactor()); 0102 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0103 } 0104 0105 arrowKeyPressed = true; 0106 slewing = true; 0107 break; 0108 0109 case Qt::Key_Up: 0110 if (Options::useAltAz()) 0111 { 0112 focus()->setAltRefracted(focus()->altRefracted().Degrees() + step * MINZOOM / Options::zoomFactor()); 0113 if (focus()->alt().Degrees() > 90.0) 0114 focus()->setAlt(90.0); 0115 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); 0116 } 0117 else 0118 { 0119 focus()->setDec(focus()->dec().Degrees() + step * MINZOOM / Options::zoomFactor()); 0120 if (focus()->dec().Degrees() > 90.0) 0121 focus()->setDec(90.0); 0122 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0123 } 0124 0125 arrowKeyPressed = true; 0126 slewing = true; 0127 break; 0128 0129 case Qt::Key_Down: 0130 if (Options::useAltAz()) 0131 { 0132 focus()->setAltRefracted(focus()->altRefracted().Degrees() - step * MINZOOM / Options::zoomFactor()); 0133 if (focus()->alt().Degrees() < -90.0) 0134 focus()->setAlt(-90.0); 0135 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); 0136 } 0137 else 0138 { 0139 focus()->setDec(focus()->dec().Degrees() - step * MINZOOM / Options::zoomFactor()); 0140 if (focus()->dec().Degrees() < -90.0) 0141 focus()->setDec(-90.0); 0142 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0143 } 0144 0145 arrowKeyPressed = true; 0146 slewing = true; 0147 break; 0148 0149 case Qt::Key_Plus: //Zoom in 0150 case Qt::Key_Equal: 0151 zoomInOrMagStep(e->modifiers()); 0152 break; 0153 0154 case Qt::Key_Minus: //Zoom out 0155 case Qt::Key_Underscore: 0156 zoomOutOrMagStep(e->modifiers()); 0157 break; 0158 0159 case Qt::Key_0: //center on Sun 0160 setClickedObject(data->skyComposite()->planet(KSPlanetBase::SUN)); 0161 setClickedPoint(clickedObject()); 0162 slotCenter(); 0163 break; 0164 0165 case Qt::Key_1: //center on Mercury 0166 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MERCURY)); 0167 setClickedPoint(clickedObject()); 0168 slotCenter(); 0169 break; 0170 0171 case Qt::Key_2: //center on Venus 0172 setClickedObject(data->skyComposite()->planet(KSPlanetBase::VENUS)); 0173 setClickedPoint(clickedObject()); 0174 slotCenter(); 0175 break; 0176 0177 case Qt::Key_3: //center on Moon 0178 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MOON)); 0179 setClickedPoint(clickedObject()); 0180 slotCenter(); 0181 break; 0182 0183 case Qt::Key_4: //center on Mars 0184 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MARS)); 0185 setClickedPoint(clickedObject()); 0186 slotCenter(); 0187 break; 0188 0189 case Qt::Key_5: //center on Jupiter 0190 setClickedObject(data->skyComposite()->planet(KSPlanetBase::JUPITER)); 0191 setClickedPoint(clickedObject()); 0192 slotCenter(); 0193 break; 0194 0195 case Qt::Key_6: //center on Saturn 0196 setClickedObject(data->skyComposite()->planet(KSPlanetBase::SATURN)); 0197 setClickedPoint(clickedObject()); 0198 slotCenter(); 0199 break; 0200 0201 case Qt::Key_7: //center on Uranus 0202 setClickedObject(data->skyComposite()->planet(KSPlanetBase::URANUS)); 0203 setClickedPoint(clickedObject()); 0204 slotCenter(); 0205 break; 0206 0207 case Qt::Key_8: //center on Neptune 0208 setClickedObject(data->skyComposite()->planet(KSPlanetBase::NEPTUNE)); 0209 setClickedPoint(clickedObject()); 0210 slotCenter(); 0211 break; 0212 0213 /*case Qt::Key_9: //center on Pluto 0214 setClickedObject( data->skyComposite()->planet( KSPlanetBase::PLUTO ) ); 0215 setClickedPoint( clickedObject() ); 0216 slotCenter(); 0217 break;*/ 0218 0219 case Qt::Key_BracketLeft: // Begin measuring angular distance 0220 if (!rulerMode) 0221 slotBeginAngularDistance(); 0222 break; 0223 case Qt::Key_Escape: // Cancel angular distance measurement 0224 { 0225 if (rulerMode) 0226 slotCancelRulerMode(); 0227 0228 if (m_fovCaptureMode) 0229 slotFinishFovCaptureMode(); 0230 break; 0231 } 0232 0233 case Qt::Key_C: //Center clicked object 0234 if (clickedObject()) 0235 slotCenter(); 0236 break; 0237 0238 case Qt::Key_D: //Details window for Clicked/Centered object 0239 { 0240 SkyObject *orig = nullptr; 0241 if (shiftPressed) 0242 { 0243 orig = clickedObject(); 0244 setClickedObject(focusObject()); 0245 } 0246 0247 if (clickedObject()) 0248 { 0249 slotDetail(); 0250 } 0251 0252 if (orig) 0253 { 0254 setClickedObject(orig); 0255 } 0256 break; 0257 } 0258 0259 case Qt::Key_P: //Show Popup menu for Clicked/Centered object 0260 if (shiftPressed) 0261 { 0262 if (focusObject()) 0263 focusObject()->showPopupMenu(pmenu, QCursor::pos()); 0264 } 0265 else 0266 { 0267 if (clickedObject()) 0268 clickedObject()->showPopupMenu(pmenu, QCursor::pos()); 0269 } 0270 break; 0271 0272 case Qt::Key_O: //Add object to Observing List 0273 { 0274 SkyObject *orig = nullptr; 0275 if (shiftPressed) 0276 { 0277 orig = clickedObject(); 0278 setClickedObject(focusObject()); 0279 } 0280 0281 if (clickedObject()) 0282 { 0283 data->observingList()->slotAddObject(); 0284 } 0285 0286 if (orig) 0287 { 0288 setClickedObject(orig); 0289 } 0290 break; 0291 } 0292 0293 case Qt::Key_L: //Toggle User label on Clicked/Centered object 0294 { 0295 SkyObject *orig = nullptr; 0296 if (shiftPressed) 0297 { 0298 orig = clickedObject(); 0299 setClickedObject(focusObject()); 0300 } 0301 0302 if (clickedObject()) 0303 { 0304 if (isObjectLabeled(clickedObject())) 0305 slotRemoveObjectLabel(); 0306 else 0307 slotAddObjectLabel(); 0308 } 0309 0310 if (orig) 0311 { 0312 setClickedObject(orig); 0313 } 0314 break; 0315 } 0316 0317 case Qt::Key_T: //Toggle planet trail on Clicked/Centered object (if solsys) 0318 { 0319 SkyObject *orig = nullptr; 0320 if (shiftPressed) 0321 { 0322 orig = clickedObject(); 0323 setClickedObject(focusObject()); 0324 } 0325 0326 KSPlanetBase *planet = dynamic_cast<KSPlanetBase *>(clickedObject()); 0327 if (planet) 0328 { 0329 if (planet->hasTrail()) 0330 slotRemovePlanetTrail(); 0331 else 0332 slotAddPlanetTrail(); 0333 } 0334 0335 if (orig) 0336 { 0337 setClickedObject(orig); 0338 } 0339 break; 0340 } 0341 0342 case Qt::Key_R: 0343 { 0344 // Toggle relativistic corrections 0345 Options::setUseRelativistic(!Options::useRelativistic()); 0346 qDebug() << Q_FUNC_INFO << "Relativistic corrections: " << Options::useRelativistic(); 0347 forceUpdate(); 0348 break; 0349 } 0350 0351 case Qt::Key_A: 0352 Options::setUseAntialias(!Options::useAntialias()); 0353 qDebug() << Q_FUNC_INFO << "Use Antialiasing: " << Options::useAntialias(); 0354 forceUpdate(); 0355 break; 0356 0357 case Qt::Key_K: 0358 { 0359 if (m_fovCaptureMode) 0360 slotCaptureFov(); 0361 break; 0362 } 0363 0364 case Qt::Key_PageUp: 0365 { 0366 KStars::Instance()->selectPreviousFov(); 0367 break; 0368 } 0369 0370 case Qt::Key_PageDown: 0371 { 0372 KStars::Instance()->selectNextFov(); 0373 break; 0374 } 0375 0376 default: 0377 // We don't want to do anything in this case. Key is unknown 0378 return; 0379 } 0380 0381 if (arrowKeyPressed) 0382 { 0383 stopTracking(); 0384 setDestination(*focus()); 0385 } 0386 0387 forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work. 0388 } 0389 0390 void SkyMap::stopTracking() 0391 { 0392 KStars *kstars = KStars::Instance(); 0393 0394 emit positionChanged(focus()); 0395 if (kstars && Options::isTracking()) 0396 kstars->slotTrack(); 0397 } 0398 0399 bool SkyMap::event(QEvent *event) 0400 { 0401 #if !defined(KSTARS_LITE) 0402 if (event->type() == QEvent::TouchBegin) 0403 { 0404 m_touchMode = true; 0405 m_pinchScale = -1; 0406 } 0407 0408 if (event->type() == QEvent::Gesture && m_touchMode) 0409 { 0410 QGestureEvent* gestureEvent = static_cast<QGestureEvent*>(event); 0411 0412 if (QPinchGesture *pinch = static_cast<QPinchGesture*>(gestureEvent->gesture(Qt::PinchGesture))) 0413 { 0414 QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags(); 0415 0416 m_pinchMode = true; 0417 if (changeFlags & QPinchGesture::ScaleFactorChanged) 0418 { 0419 if (m_pinchScale == -1) 0420 { 0421 m_pinchScale = pinch->totalScaleFactor(); 0422 return true; 0423 } 0424 if (pinch->totalScaleFactor() - m_pinchScale > 0.1) 0425 { 0426 m_pinchScale = pinch->totalScaleFactor(); 0427 zoomInOrMagStep(0); 0428 return true; 0429 } 0430 if (pinch->totalScaleFactor() - m_pinchScale < -0.1) 0431 { 0432 m_pinchScale = pinch->totalScaleFactor(); 0433 zoomOutOrMagStep(0); 0434 return true; 0435 } 0436 } 0437 } 0438 if (QTapAndHoldGesture *tapAndHold = static_cast<QTapAndHoldGesture*>(gestureEvent->gesture(Qt::TapAndHoldGesture))) 0439 { 0440 m_tapAndHoldMode = true; 0441 if (tapAndHold->state() == Qt::GestureFinished) 0442 { 0443 if (clickedObject()) 0444 { 0445 clickedObject()->showPopupMenu(pmenu, tapAndHold->position().toPoint()); 0446 } 0447 else 0448 { 0449 pmenu->createEmptyMenu(clickedPoint()); 0450 pmenu->popup(tapAndHold->position().toPoint()); 0451 } 0452 m_touchMode = false; 0453 m_pinchMode = false; 0454 m_tapAndHoldMode = false; 0455 } 0456 } 0457 return true; 0458 } 0459 #endif 0460 return QGraphicsView::event(event); 0461 } 0462 0463 void SkyMap::keyReleaseEvent(QKeyEvent *e) 0464 { 0465 switch (e->key()) 0466 { 0467 case Qt::Key_Plus: //Zoom in 0468 case Qt::Key_Equal: 0469 case Qt::Key_Minus: //Zoom out 0470 case Qt::Key_Underscore: 0471 0472 case Qt::Key_Left: //no break; continue to Qt::Key_Down 0473 case Qt::Key_Right: //no break; continue to Qt::Key_Down 0474 case Qt::Key_Up: //no break; continue to Qt::Key_Down 0475 case Qt::Key_Down: 0476 slewing = false; 0477 0478 if (Options::useAltAz()) 0479 setDestinationAltAz(focus()->alt(), focus()->az(), false); 0480 else 0481 setDestination(*focus()); 0482 0483 showFocusCoords(); 0484 forceUpdate(); // Need a full update to draw faint objects that are not drawn while slewing. 0485 break; 0486 } 0487 } 0488 0489 void SkyMap::mouseMoveEvent(QMouseEvent *e) 0490 { 0491 #if !defined(KSTARS_LITE) 0492 // Skip touch points 0493 if (m_pinchMode || m_tapAndHoldMode || (m_touchMode && e->globalX() == 0 && e->globalY() == 0)) 0494 return; 0495 #endif 0496 0497 if (Options::useHoverLabel()) 0498 { 0499 //Start a single-shot timer to monitor whether we are currently hovering. 0500 //The idea is that whenever a moveEvent occurs, the timer is reset. It 0501 //will only timeout if there are no move events for HOVER_INTERVAL ms 0502 m_HoverTimer.start(HOVER_INTERVAL); 0503 QToolTip::hideText(); 0504 } 0505 0506 //Are we defining a ZoomRect? 0507 if (ZoomRect.center().x() > 0 && ZoomRect.center().y() > 0) 0508 { 0509 //cancel operation if the user let go of CTRL 0510 if (!(e->modifiers() & Qt::ControlModifier)) 0511 { 0512 ZoomRect = QRect(); //invalidate ZoomRect 0513 update(); 0514 } 0515 else 0516 { 0517 //Resize the rectangle so that it passes through the cursor position 0518 QPoint pcenter = ZoomRect.center(); 0519 int dx = abs(e->x() - pcenter.x()); 0520 int dy = abs(e->y() - pcenter.y()); 0521 if (dx == 0 || float(dy) / float(dx) > float(height()) / float(width())) 0522 { 0523 //Size rect by height 0524 ZoomRect.setHeight(2 * dy); 0525 ZoomRect.setWidth(2 * dy * width() / height()); 0526 } 0527 else 0528 { 0529 //Size rect by height 0530 ZoomRect.setWidth(2 * dx); 0531 ZoomRect.setHeight(2 * dx * height() / width()); 0532 } 0533 ZoomRect.moveCenter(pcenter); //reset center 0534 0535 update(); 0536 return; 0537 } 0538 } 0539 0540 // Are we setting the skymap rotation? 0541 if (rotationStart.x() > 0 && rotationStart.y() > 0) 0542 { 0543 // stop the operation if the user let go of SHIFT 0544 if (!(e->modifiers() & Qt::ShiftModifier)) 0545 { 0546 rotationStart = QPoint(); // invalidate 0547 rotationStartAngle = dms(); // NaN 0548 slewing = false; 0549 forceUpdate(); 0550 return; 0551 } 0552 else 0553 { 0554 // Compute the rotation 0555 const float start_x = rotationStart.x() - width() / 2.0f; 0556 const float start_y = height() / 2.0f - rotationStart.y(); 0557 0558 const float curr_x = e->pos().x() - width() / 2.0f; 0559 const float curr_y = height() / 2.0f - e->pos().y(); 0560 0561 const dms angle {(std::atan2(curr_y, curr_x) - std::atan2(start_y, start_x)) / dms::DegToRad }; 0562 slotSetSkyRotation((rotationStartAngle - angle).Degrees()); 0563 return; 0564 } 0565 } 0566 0567 if (projector()->unusablePoint(e->pos())) 0568 return; // break if point is unusable 0569 0570 //determine RA, Dec of mouse pointer 0571 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat()); 0572 0573 double dyPix = 0.5 * height() - e->y(); 0574 if (midMouseButtonDown) //zoom according to y-offset 0575 { 0576 float yoff = dyPix - y0; 0577 if (yoff > 10) 0578 { 0579 y0 = dyPix; 0580 slotZoomIn(); 0581 } 0582 if (yoff < -10) 0583 { 0584 y0 = dyPix; 0585 slotZoomOut(); 0586 } 0587 } 0588 0589 if (mouseButtonDown) 0590 { 0591 #ifdef HAVE_INDI 0592 if (Options::showMosaicPanel()) 0593 { 0594 auto tiles = KStarsData::Instance()->skyComposite()->mosaicComponent()->tiles(); 0595 0596 if (tiles->operationMode() == MosaicTiles::MODE_PLANNING) 0597 { 0598 // Check if mouse point within Mosaic FOV bounds. 0599 auto mosaicFOV = tiles->mosaicFOV(); 0600 auto upperRA = tiles->ra0().Degrees() + mosaicFOV.width() / 60; 0601 auto lowerRA = tiles->ra0().Degrees() - mosaicFOV.width() / 60; 0602 auto upperDE = tiles->dec0().Degrees() + mosaicFOV.height() / 60; 0603 auto lowerDE = tiles->dec0().Degrees() - mosaicFOV.height() / 60; 0604 0605 auto mouseRA = m_MousePoint.ra().Degrees(); 0606 auto mouseDE = m_MousePoint.dec().Degrees(); 0607 0608 // If mouse point is within, then behave like drag and drop 0609 if (mouseRA > lowerRA && mouseRA < upperRA && mouseDE > lowerDE && mouseDE < upperDE) 0610 { 0611 if (!mouseDragCursor) 0612 setMouseDragCursor(); 0613 0614 dms dRA = m_MousePoint.ra() - clickedPoint()->ra(); 0615 dms dDec = m_MousePoint.dec() - clickedPoint()->dec(); 0616 0617 // Emit difference between mouse point and clicked point. 0618 emit mosaicCenterChanged(dRA, dDec); 0619 0620 // Update mouse and clicked points. 0621 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat()); 0622 setClickedPoint(&m_MousePoint); 0623 update(); 0624 return; 0625 } 0626 } 0627 } 0628 #endif 0629 0630 // set the mouseMoveCursor and set slewing=true, if they are not set yet 0631 if (!mouseMoveCursor) 0632 setMouseMoveCursor(); 0633 if (!slewing) 0634 { 0635 slewing = true; 0636 stopTracking(); //toggle tracking off 0637 } 0638 0639 //Update focus such that the sky coords at mouse cursor remain approximately constant 0640 if (Options::useAltAz()) 0641 { 0642 m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0643 clickedPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0644 dms dAz = m_MousePoint.az() - clickedPoint()->az(); 0645 dms dAlt = m_MousePoint.altRefracted() - clickedPoint()->altRefracted(); 0646 focus()->setAz(focus()->az().Degrees() - dAz.Degrees()); //move focus in opposite direction 0647 focus()->setAz(focus()->az().reduce()); 0648 focus()->setAltRefracted(KSUtils::clamp(focus()->altRefracted().Degrees() - dAlt.Degrees(), -90.0, 90.0)); 0649 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); 0650 } 0651 else 0652 { 0653 dms dRA = m_MousePoint.ra() - clickedPoint()->ra(); 0654 dms dDec = m_MousePoint.dec() - clickedPoint()->dec(); 0655 focus()->setRA(focus()->ra().Hours() - dRA.Hours()); //move focus in opposite direction 0656 focus()->setRA(focus()->ra().reduce()); 0657 focus()->setDec(KSUtils::clamp(focus()->dec().Degrees() - dDec.Degrees(), -90.0, 90.0)); 0658 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0659 } 0660 showFocusCoords(); 0661 0662 //redetermine RA, Dec of mouse pointer, using new focus 0663 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat()); 0664 setClickedPoint(&m_MousePoint); 0665 forceUpdate(); // must be new computed 0666 } 0667 else //mouse button not down 0668 { 0669 if (Options::useAltAz()) 0670 m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0671 emit mousePointChanged(&m_MousePoint); 0672 } 0673 } 0674 0675 void SkyMap::wheelEvent(QWheelEvent *e) 0676 { 0677 if (e->angleDelta().y() > 0) 0678 zoomInOrMagStep(e->modifiers()); 0679 else if (e->angleDelta().y() < 0) 0680 zoomOutOrMagStep(e->modifiers()); 0681 } 0682 0683 void SkyMap::mouseReleaseEvent(QMouseEvent *e) 0684 { 0685 #if !defined(KSTARS_LITE) 0686 if (m_touchMode) 0687 { 0688 m_touchMode = false; 0689 m_pinchMode = false; 0690 m_tapAndHoldMode = false; 0691 } 0692 #endif 0693 0694 if (ZoomRect.isValid()) 0695 { 0696 stopTracking(); 0697 SkyPoint newcenter = projector()->fromScreen(ZoomRect.center(), data->lst(), data->geo()->lat()); 0698 setFocus(&newcenter); 0699 setDestination(newcenter); 0700 0701 //Zoom in on center of Zoom Circle, by a factor equal to the ratio 0702 //of the sky pixmap's width to the Zoom Circle's diameter 0703 float factor = float(width()) / float(ZoomRect.width()); 0704 setZoomFactor(Options::zoomFactor() * factor); 0705 } 0706 0707 setMouseCursorShape(static_cast<Cursor>(Options::defaultCursor())); 0708 0709 ZoomRect = QRect(); //invalidate ZoomRect 0710 0711 if (m_previewLegend) 0712 { 0713 slotCancelLegendPreviewMode(); 0714 } 0715 0716 // Are we setting the skymap rotation? 0717 if (rotationStart.x() > 0 && rotationStart.y() > 0) 0718 { 0719 rotationStart = QPoint(); // invalidate 0720 rotationStartAngle = dms(); // NaN 0721 slewing = false; 0722 forceUpdateNow(); 0723 return; 0724 } 0725 0726 //false if double-clicked, because it's unset there. 0727 if (mouseButtonDown) 0728 { 0729 mouseButtonDown = false; 0730 if (slewing) 0731 { 0732 slewing = false; 0733 if (Options::useAltAz()) 0734 setDestinationAltAz(focus()->alt(), focus()->az(), false); 0735 else 0736 setDestination(*focus()); 0737 } 0738 else if (Options::leftClickSelectsObject()) 0739 mouseDoubleClickEvent(e); 0740 forceUpdate(); // is needed because after moving the sky not all stars are shown 0741 } 0742 // if middle button was pressed unset here 0743 midMouseButtonDown = false; 0744 } 0745 0746 void SkyMap::mousePressEvent(QMouseEvent *e) 0747 { 0748 KStars *kstars = KStars::Instance(); 0749 0750 if ((e->modifiers() & Qt::ControlModifier) && (e->button() == Qt::LeftButton)) 0751 { 0752 ZoomRect.moveCenter(e->pos()); 0753 setZoomMouseCursor(); 0754 update(); //refresh without redrawing skymap 0755 return; 0756 } 0757 0758 if ((e->modifiers() & Qt::ShiftModifier) && (e->button() == Qt::LeftButton)) 0759 { 0760 // Skymap rotation mode 0761 rotationStart = e->pos(); 0762 rotationStartAngle = dms(Options::skyRotation()); 0763 slewing = true; 0764 setRotationMouseCursor(); 0765 forceUpdate(); 0766 return; 0767 } 0768 0769 // if button is down and cursor is not moved set the move cursor after 500 ms 0770 //QTimer::singleShot(500, this, SLOT(setMouseMoveCursor())); 0771 0772 // break if point is unusable 0773 if (projector()->unusablePoint(e->pos())) 0774 return; 0775 0776 if (!midMouseButtonDown && e->button() == Qt::MidButton) 0777 { 0778 y0 = 0.5 * height() - e->y(); //record y pixel coordinate for middle-button zooming 0779 midMouseButtonDown = true; 0780 } 0781 0782 if (!mouseButtonDown) 0783 { 0784 if (e->button() == Qt::LeftButton) 0785 { 0786 mouseButtonDown = true; 0787 } 0788 0789 //determine RA, Dec of mouse pointer 0790 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat()); 0791 setClickedPoint(&m_MousePoint); 0792 0793 //Find object nearest to clickedPoint() 0794 double maxrad = 5000.0 / Options::zoomFactor(); 0795 SkyObject *obj = data->skyComposite()->objectNearest(clickedPoint(), maxrad); 0796 setClickedObject(obj); 0797 if (obj) 0798 setClickedPoint(obj); 0799 0800 switch (e->button()) 0801 { 0802 case Qt::LeftButton: 0803 { 0804 QString name; 0805 if (clickedObject()) 0806 { 0807 name = clickedObject()->translatedLongName(); 0808 emit objectClicked(clickedObject()); 0809 } 0810 else 0811 name = i18n("Empty sky"); 0812 //kstars->statusBar()->changeItem(name, 0 ); 0813 kstars->statusBar()->showMessage(name, 0); 0814 0815 emit positionClicked(&m_MousePoint); 0816 } 0817 0818 break; 0819 case Qt::RightButton: 0820 if (rulerMode) 0821 { 0822 // Compute angular distance. 0823 slotEndRulerMode(); 0824 } 0825 else 0826 { 0827 // Show popup menu 0828 if (clickedObject()) 0829 { 0830 clickedObject()->showPopupMenu(pmenu, QCursor::pos()); 0831 } 0832 else 0833 { 0834 pmenu->createEmptyMenu(clickedPoint()); 0835 pmenu->popup(QCursor::pos()); 0836 } 0837 } 0838 break; 0839 default: 0840 ; 0841 } 0842 } 0843 } 0844 0845 void SkyMap::mouseDoubleClickEvent(QMouseEvent *e) 0846 { 0847 if (e->button() == Qt::LeftButton && !projector()->unusablePoint(e->pos())) 0848 { 0849 mouseButtonDown = false; 0850 if (e->x() != width() / 2 || e->y() != height() / 2) 0851 slotCenter(); 0852 } 0853 } 0854 0855 double SkyMap::zoomFactor(const int modifier) 0856 { 0857 double factor = (modifier & Qt::ControlModifier) ? DZOOM : (Options::zoomScrollFactor() + 1); 0858 if (modifier & Qt::ShiftModifier) 0859 factor = sqrt(factor); 0860 return factor; 0861 } 0862 0863 void SkyMap::zoomInOrMagStep(const int modifier) 0864 { 0865 if (modifier & Qt::AltModifier) 0866 incMagLimit(modifier); 0867 else 0868 setZoomFactor(Options::zoomFactor() * zoomFactor(modifier)); 0869 } 0870 0871 void SkyMap::zoomOutOrMagStep(const int modifier) 0872 { 0873 if (modifier & Qt::AltModifier) 0874 decMagLimit(modifier); 0875 else 0876 setZoomFactor(Options::zoomFactor() / zoomFactor(modifier)); 0877 } 0878 0879 double SkyMap::magFactor(const int modifier) 0880 { 0881 double factor = (modifier & Qt::ControlModifier) ? 0.1 : 0.5; 0882 if (modifier & Qt::ShiftModifier) 0883 factor *= 2.0; 0884 return factor; 0885 } 0886 0887 void SkyMap::incMagLimit(const int modifier) 0888 { 0889 double limit = 2.222 * log10(static_cast<double>(Options::starDensity())) + 0.35; 0890 limit += magFactor(modifier); 0891 if (limit > 5.75954) 0892 limit = 5.75954; 0893 Options::setStarDensity(pow(10, (limit - 0.35) / 2.222)); 0894 //printf("maglim set to %3.1f\n", limit); 0895 forceUpdate(); 0896 } 0897 0898 void SkyMap::decMagLimit(const int modifier) 0899 { 0900 double limit = 2.222 * log10(static_cast<double>(Options::starDensity())) + 0.35; 0901 limit -= magFactor(modifier); 0902 if (limit < 1.18778) 0903 limit = 1.18778; 0904 Options::setStarDensity(pow(10, (limit - 0.35) / 2.222)); 0905 //printf("maglim set to %3.1f\n", limit); 0906 forceUpdate(); 0907 }