1 /*
2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 //This file contains Event handlers for the SkyMap class.
8
9 #include "skymap.h"
10
11 #include "ksplanetbase.h"
12 #include "kspopupmenu.h"
13 #include "kstars.h"
14 #include "observinglist.h"
15 #include "Options.h"
16 #include "skyglpainter.h"
17 #include "skyqpainter.h"
18 #include "printing/simplefovexporter.h"
19 #include "skycomponents/skylabeler.h"
20 #include "skycomponents/skymapcomposite.h"
21 #include "skycomponents/starcomponent.h"
22 #include "widgets/infoboxwidget.h"
23
24 #include <QGestureEvent>
25 #include <QStatusBar>
26 #include <QToolTip>
27
resizeEvent(QResizeEvent *)28 void SkyMap::resizeEvent(QResizeEvent *)
29 {
30 computeSkymap = true; // skymap must be new computed
31
32 //FIXME: No equivalent for this line in Qt4 ??
33 // if ( testWState( Qt::WState_AutoMask ) ) updateMask();
34
35 // Resize the widget that draws the sky map.
36 // FIXME: The resize event doesn't pass to children. Any better way of doing this?
37 m_SkyMapDraw->resize(size());
38
39 // Resize infoboxes container.
40 // FIXME: this is not really pretty. Maybe there are some better way to this???
41 m_iboxes->resize(size());
42 }
43
keyPressEvent(QKeyEvent * e)44 void SkyMap::keyPressEvent(QKeyEvent *e)
45 {
46 bool arrowKeyPressed(false);
47 bool shiftPressed(false);
48 float step = 1.0;
49 if (e->modifiers() & Qt::ShiftModifier)
50 {
51 step = 10.0;
52 shiftPressed = true;
53 }
54
55 //If the DBus resume key is not empty, then DBus processing is
56 //paused while we wait for a keypress
57 if (!data->resumeKey.isEmpty() && QKeySequence(e->key()) == data->resumeKey)
58 {
59 //The resumeKey was pressed. Signal that it was pressed by
60 //resetting it to empty; this will break the loop in
61 //KStars::waitForKey()
62 data->resumeKey = QKeySequence();
63 return;
64 }
65
66 if (m_previewLegend)
67 {
68 slotCancelLegendPreviewMode();
69 }
70
71 switch (e->key())
72 {
73 case Qt::Key_Left:
74 if (Options::useAltAz())
75 {
76 focus()->setAz(dms(focus()->az().Degrees() - step * MINZOOM / Options::zoomFactor()).reduce());
77 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
78 }
79 else
80 {
81 focus()->setRA(focus()->ra().Hours() + 0.05 * step * MINZOOM / Options::zoomFactor());
82 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
83 }
84
85 arrowKeyPressed = true;
86 slewing = true;
87 break;
88
89 case Qt::Key_Right:
90 if (Options::useAltAz())
91 {
92 focus()->setAz(dms(focus()->az().Degrees() + step * MINZOOM / Options::zoomFactor()).reduce());
93 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
94 }
95 else
96 {
97 focus()->setRA(focus()->ra().Hours() - 0.05 * step * MINZOOM / Options::zoomFactor());
98 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
99 }
100
101 arrowKeyPressed = true;
102 slewing = true;
103 break;
104
105 case Qt::Key_Up:
106 if (Options::useAltAz())
107 {
108 focus()->setAltRefracted(focus()->altRefracted().Degrees() + step * MINZOOM / Options::zoomFactor());
109 if (focus()->alt().Degrees() > 90.0)
110 focus()->setAlt(90.0);
111 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
112 }
113 else
114 {
115 focus()->setDec(focus()->dec().Degrees() + step * MINZOOM / Options::zoomFactor());
116 if (focus()->dec().Degrees() > 90.0)
117 focus()->setDec(90.0);
118 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
119 }
120
121 arrowKeyPressed = true;
122 slewing = true;
123 break;
124
125 case Qt::Key_Down:
126 if (Options::useAltAz())
127 {
128 focus()->setAltRefracted(focus()->altRefracted().Degrees() - step * MINZOOM / Options::zoomFactor());
129 if (focus()->alt().Degrees() < -90.0)
130 focus()->setAlt(-90.0);
131 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
132 }
133 else
134 {
135 focus()->setDec(focus()->dec().Degrees() - step * MINZOOM / Options::zoomFactor());
136 if (focus()->dec().Degrees() < -90.0)
137 focus()->setDec(-90.0);
138 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
139 }
140
141 arrowKeyPressed = true;
142 slewing = true;
143 break;
144
145 case Qt::Key_Plus: //Zoom in
146 case Qt::Key_Equal:
147 zoomInOrMagStep(e->modifiers());
148 break;
149
150 case Qt::Key_Minus: //Zoom out
151 case Qt::Key_Underscore:
152 zoomOutOrMagStep(e->modifiers());
153 break;
154
155 case Qt::Key_0: //center on Sun
156 setClickedObject(data->skyComposite()->planet(KSPlanetBase::SUN));
157 setClickedPoint(clickedObject());
158 slotCenter();
159 break;
160
161 case Qt::Key_1: //center on Mercury
162 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MERCURY));
163 setClickedPoint(clickedObject());
164 slotCenter();
165 break;
166
167 case Qt::Key_2: //center on Venus
168 setClickedObject(data->skyComposite()->planet(KSPlanetBase::VENUS));
169 setClickedPoint(clickedObject());
170 slotCenter();
171 break;
172
173 case Qt::Key_3: //center on Moon
174 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MOON));
175 setClickedPoint(clickedObject());
176 slotCenter();
177 break;
178
179 case Qt::Key_4: //center on Mars
180 setClickedObject(data->skyComposite()->planet(KSPlanetBase::MARS));
181 setClickedPoint(clickedObject());
182 slotCenter();
183 break;
184
185 case Qt::Key_5: //center on Jupiter
186 setClickedObject(data->skyComposite()->planet(KSPlanetBase::JUPITER));
187 setClickedPoint(clickedObject());
188 slotCenter();
189 break;
190
191 case Qt::Key_6: //center on Saturn
192 setClickedObject(data->skyComposite()->planet(KSPlanetBase::SATURN));
193 setClickedPoint(clickedObject());
194 slotCenter();
195 break;
196
197 case Qt::Key_7: //center on Uranus
198 setClickedObject(data->skyComposite()->planet(KSPlanetBase::URANUS));
199 setClickedPoint(clickedObject());
200 slotCenter();
201 break;
202
203 case Qt::Key_8: //center on Neptune
204 setClickedObject(data->skyComposite()->planet(KSPlanetBase::NEPTUNE));
205 setClickedPoint(clickedObject());
206 slotCenter();
207 break;
208
209 /*case Qt::Key_9: //center on Pluto
210 setClickedObject( data->skyComposite()->planet( KSPlanetBase::PLUTO ) );
211 setClickedPoint( clickedObject() );
212 slotCenter();
213 break;*/
214
215 case Qt::Key_BracketLeft: // Begin measuring angular distance
216 if (!rulerMode)
217 slotBeginAngularDistance();
218 break;
219 case Qt::Key_Escape: // Cancel angular distance measurement
220 {
221 if (rulerMode)
222 slotCancelRulerMode();
223
224 if (m_fovCaptureMode)
225 slotFinishFovCaptureMode();
226 break;
227 }
228
229 case Qt::Key_C: //Center clicked object
230 if (clickedObject())
231 slotCenter();
232 break;
233
234 case Qt::Key_D: //Details window for Clicked/Centered object
235 {
236 SkyObject *orig = nullptr;
237 if (shiftPressed)
238 {
239 orig = clickedObject();
240 setClickedObject(focusObject());
241 }
242
243 if (clickedObject())
244 {
245 slotDetail();
246 }
247
248 if (orig)
249 {
250 setClickedObject(orig);
251 }
252 break;
253 }
254
255 case Qt::Key_P: //Show Popup menu for Clicked/Centered object
256 if (shiftPressed)
257 {
258 if (focusObject())
259 focusObject()->showPopupMenu(pmenu, QCursor::pos());
260 }
261 else
262 {
263 if (clickedObject())
264 clickedObject()->showPopupMenu(pmenu, QCursor::pos());
265 }
266 break;
267
268 case Qt::Key_O: //Add object to Observing List
269 {
270 SkyObject *orig = nullptr;
271 if (shiftPressed)
272 {
273 orig = clickedObject();
274 setClickedObject(focusObject());
275 }
276
277 if (clickedObject())
278 {
279 data->observingList()->slotAddObject();
280 }
281
282 if (orig)
283 {
284 setClickedObject(orig);
285 }
286 break;
287 }
288
289 case Qt::Key_L: //Toggle User label on Clicked/Centered object
290 {
291 SkyObject *orig = nullptr;
292 if (shiftPressed)
293 {
294 orig = clickedObject();
295 setClickedObject(focusObject());
296 }
297
298 if (clickedObject())
299 {
300 if (isObjectLabeled(clickedObject()))
301 slotRemoveObjectLabel();
302 else
303 slotAddObjectLabel();
304 }
305
306 if (orig)
307 {
308 setClickedObject(orig);
309 }
310 break;
311 }
312
313 case Qt::Key_T: //Toggle planet trail on Clicked/Centered object (if solsys)
314 {
315 SkyObject *orig = nullptr;
316 if (shiftPressed)
317 {
318 orig = clickedObject();
319 setClickedObject(focusObject());
320 }
321
322 KSPlanetBase *planet = dynamic_cast<KSPlanetBase *>(clickedObject());
323 if (planet)
324 {
325 if (planet->hasTrail())
326 slotRemovePlanetTrail();
327 else
328 slotAddPlanetTrail();
329 }
330
331 if (orig)
332 {
333 setClickedObject(orig);
334 }
335 break;
336 }
337
338 case Qt::Key_R:
339 {
340 // Toggle relativistic corrections
341 Options::setUseRelativistic(!Options::useRelativistic());
342 qDebug() << "Relativistic corrections: " << Options::useRelativistic();
343 forceUpdate();
344 break;
345 }
346
347 case Qt::Key_A:
348 Options::setUseAntialias(!Options::useAntialias());
349 qDebug() << "Use Antialiasing: " << Options::useAntialias();
350 forceUpdate();
351 break;
352
353 case Qt::Key_K:
354 {
355 if (m_fovCaptureMode)
356 slotCaptureFov();
357 break;
358 }
359
360 case Qt::Key_PageUp:
361 {
362 KStars::Instance()->selectPreviousFov();
363 break;
364 }
365
366 case Qt::Key_PageDown:
367 {
368 KStars::Instance()->selectNextFov();
369 break;
370 }
371
372 default:
373 // We don't want to do anything in this case. Key is unknown
374 return;
375 }
376
377 if (arrowKeyPressed)
378 {
379 stopTracking();
380 setDestination(*focus());
381 }
382
383 forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work.
384 }
385
stopTracking()386 void SkyMap::stopTracking()
387 {
388 KStars *kstars = KStars::Instance();
389
390 emit positionChanged(focus());
391 if (kstars && Options::isTracking())
392 kstars->slotTrack();
393 }
394
event(QEvent * event)395 bool SkyMap::event(QEvent *event)
396 {
397 #if !defined(KSTARS_LITE)
398 if (event->type() == QEvent::TouchBegin)
399 {
400 m_touchMode = true;
401 m_pinchScale = -1;
402 }
403
404 if (event->type() == QEvent::Gesture && m_touchMode)
405 {
406 QGestureEvent* gestureEvent = static_cast<QGestureEvent*>(event);
407
408 if (QPinchGesture *pinch = static_cast<QPinchGesture*>(gestureEvent->gesture(Qt::PinchGesture)))
409 {
410 QPinchGesture::ChangeFlags changeFlags = pinch->changeFlags();
411
412 m_pinchMode = true;
413 if (changeFlags & QPinchGesture::ScaleFactorChanged)
414 {
415 if (m_pinchScale == -1)
416 {
417 m_pinchScale = pinch->totalScaleFactor();
418 return true;
419 }
420 if (pinch->totalScaleFactor() - m_pinchScale > 0.1)
421 {
422 m_pinchScale = pinch->totalScaleFactor();
423 zoomInOrMagStep(0);
424 return true;
425 }
426 if (pinch->totalScaleFactor() - m_pinchScale < -0.1)
427 {
428 m_pinchScale = pinch->totalScaleFactor();
429 zoomOutOrMagStep(0);
430 return true;
431 }
432 }
433 }
434 if (QTapAndHoldGesture *tapAndHold = static_cast<QTapAndHoldGesture*>(gestureEvent->gesture(Qt::TapAndHoldGesture)))
435 {
436 m_tapAndHoldMode = true;
437 if (tapAndHold->state() == Qt::GestureFinished)
438 {
439 if (clickedObject())
440 {
441 clickedObject()->showPopupMenu(pmenu, tapAndHold->position().toPoint());
442 }
443 else
444 {
445 pmenu->createEmptyMenu(clickedPoint());
446 pmenu->popup(tapAndHold->position().toPoint());
447 }
448 m_touchMode = false;
449 m_pinchMode = false;
450 m_tapAndHoldMode = false;
451 }
452 }
453 return true;
454 }
455 #endif
456 return QGraphicsView::event(event);
457 }
458
keyReleaseEvent(QKeyEvent * e)459 void SkyMap::keyReleaseEvent(QKeyEvent *e)
460 {
461 switch (e->key())
462 {
463 case Qt::Key_Plus: //Zoom in
464 case Qt::Key_Equal:
465 case Qt::Key_Minus: //Zoom out
466 case Qt::Key_Underscore:
467
468 case Qt::Key_Left: //no break; continue to Qt::Key_Down
469 case Qt::Key_Right: //no break; continue to Qt::Key_Down
470 case Qt::Key_Up: //no break; continue to Qt::Key_Down
471 case Qt::Key_Down:
472 slewing = false;
473
474 if (Options::useAltAz())
475 setDestinationAltAz(focus()->alt(), focus()->az(), false);
476 else
477 setDestination(*focus());
478
479 showFocusCoords();
480 forceUpdate(); // Need a full update to draw faint objects that are not drawn while slewing.
481 break;
482 }
483 }
484
mouseMoveEvent(QMouseEvent * e)485 void SkyMap::mouseMoveEvent(QMouseEvent *e)
486 {
487 #if !defined(KSTARS_LITE)
488 // Skip touch points
489 if (m_pinchMode || m_tapAndHoldMode || (m_touchMode && e->globalX() == 0 && e->globalY() == 0))
490 return;
491 #endif
492
493 if (Options::useHoverLabel())
494 {
495 //Start a single-shot timer to monitor whether we are currently hovering.
496 //The idea is that whenever a moveEvent occurs, the timer is reset. It
497 //will only timeout if there are no move events for HOVER_INTERVAL ms
498 m_HoverTimer.start(HOVER_INTERVAL);
499 QToolTip::hideText();
500 }
501
502 //Are we defining a ZoomRect?
503 if (ZoomRect.center().x() > 0 && ZoomRect.center().y() > 0)
504 {
505 //cancel operation if the user let go of CTRL
506 if (!(e->modifiers() & Qt::ControlModifier))
507 {
508 ZoomRect = QRect(); //invalidate ZoomRect
509 update();
510 }
511 else
512 {
513 //Resize the rectangle so that it passes through the cursor position
514 QPoint pcenter = ZoomRect.center();
515 int dx = abs(e->x() - pcenter.x());
516 int dy = abs(e->y() - pcenter.y());
517 if (dx == 0 || float(dy) / float(dx) > float(height()) / float(width()))
518 {
519 //Size rect by height
520 ZoomRect.setHeight(2 * dy);
521 ZoomRect.setWidth(2 * dy * width() / height());
522 }
523 else
524 {
525 //Size rect by height
526 ZoomRect.setWidth(2 * dx);
527 ZoomRect.setHeight(2 * dx * height() / width());
528 }
529 ZoomRect.moveCenter(pcenter); //reset center
530
531 update();
532 return;
533 }
534 }
535
536 if (projector()->unusablePoint(e->pos()))
537 return; // break if point is unusable
538
539 //determine RA, Dec of mouse pointer
540 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat());
541
542 double dyPix = 0.5 * height() - e->y();
543 if (midMouseButtonDown) //zoom according to y-offset
544 {
545 float yoff = dyPix - y0;
546 if (yoff > 10)
547 {
548 y0 = dyPix;
549 slotZoomIn();
550 }
551 if (yoff < -10)
552 {
553 y0 = dyPix;
554 slotZoomOut();
555 }
556 }
557
558 if (mouseButtonDown)
559 {
560 // set the mouseMoveCursor and set slewing=true, if they are not set yet
561 if (!mouseMoveCursor)
562 setMouseMoveCursor();
563 if (!slewing)
564 {
565 slewing = true;
566 stopTracking(); //toggle tracking off
567 }
568
569 //Update focus such that the sky coords at mouse cursor remain approximately constant
570 if (Options::useAltAz())
571 {
572 m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat());
573 clickedPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
574 dms dAz = m_MousePoint.az() - clickedPoint()->az();
575 dms dAlt = m_MousePoint.altRefracted() - clickedPoint()->altRefracted();
576 focus()->setAz(focus()->az().Degrees() - dAz.Degrees()); //move focus in opposite direction
577 focus()->setAz(focus()->az().reduce());
578 focus()->setAltRefracted(KSUtils::clamp(focus()->altRefracted().Degrees() - dAlt.Degrees(), -90.0, 90.0));
579 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
580 }
581 else
582 {
583 dms dRA = m_MousePoint.ra() - clickedPoint()->ra();
584 dms dDec = m_MousePoint.dec() - clickedPoint()->dec();
585 focus()->setRA(focus()->ra().Hours() - dRA.Hours()); //move focus in opposite direction
586 focus()->setRA(focus()->ra().reduce());
587 focus()->setDec(KSUtils::clamp(focus()->dec().Degrees() - dDec.Degrees(), -90.0, 90.0));
588 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
589 }
590 showFocusCoords();
591
592 //redetermine RA, Dec of mouse pointer, using new focus
593 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat());
594 setClickedPoint(&m_MousePoint);
595
596 forceUpdate(); // must be new computed
597 }
598 else //mouse button not down
599 {
600 if (Options::useAltAz())
601 m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat());
602 emit mousePointChanged(&m_MousePoint);
603 }
604 }
605
wheelEvent(QWheelEvent * e)606 void SkyMap::wheelEvent(QWheelEvent *e)
607 {
608 if (e->delta() > 0)
609 zoomInOrMagStep(e->modifiers());
610 else if (e->delta() < 0)
611 zoomOutOrMagStep(e->modifiers());
612 }
613
mouseReleaseEvent(QMouseEvent * e)614 void SkyMap::mouseReleaseEvent(QMouseEvent *e)
615 {
616 #if !defined(KSTARS_LITE)
617 if (m_touchMode)
618 {
619 m_touchMode = false;
620 m_pinchMode = false;
621 m_tapAndHoldMode = false;
622 }
623 #endif
624
625 if (ZoomRect.isValid())
626 {
627 stopTracking();
628 SkyPoint newcenter = projector()->fromScreen(ZoomRect.center(), data->lst(), data->geo()->lat());
629 setFocus(&newcenter);
630 setDestination(newcenter);
631
632 //Zoom in on center of Zoom Circle, by a factor equal to the ratio
633 //of the sky pixmap's width to the Zoom Circle's diameter
634 float factor = float(width()) / float(ZoomRect.width());
635 setZoomFactor(Options::zoomFactor() * factor);
636 }
637
638 setMouseCursorShape(static_cast<Cursor>(Options::defaultCursor()));
639
640 ZoomRect = QRect(); //invalidate ZoomRect
641
642 if (m_previewLegend)
643 {
644 slotCancelLegendPreviewMode();
645 }
646
647 //false if double-clicked, because it's unset there.
648 if (mouseButtonDown)
649 {
650 mouseButtonDown = false;
651 if (slewing)
652 {
653 slewing = false;
654 if (Options::useAltAz())
655 setDestinationAltAz(focus()->alt(), focus()->az(), false);
656 else
657 setDestination(*focus());
658 }
659 else if (Options::leftClickSelectsObject())
660 mouseDoubleClickEvent(e);
661 forceUpdate(); // is needed because after moving the sky not all stars are shown
662 }
663 // if middle button was pressed unset here
664 midMouseButtonDown = false;
665 }
666
mousePressEvent(QMouseEvent * e)667 void SkyMap::mousePressEvent(QMouseEvent *e)
668 {
669 KStars *kstars = KStars::Instance();
670
671 if ((e->modifiers() & Qt::ControlModifier) && (e->button() == Qt::LeftButton))
672 {
673 ZoomRect.moveCenter(e->pos());
674 setZoomMouseCursor();
675 update(); //refresh without redrawing skymap
676 return;
677 }
678
679 // if button is down and cursor is not moved set the move cursor after 500 ms
680 QTimer::singleShot(500, this, SLOT(setMouseMoveCursor()));
681
682 // break if point is unusable
683 if (projector()->unusablePoint(e->pos()))
684 return;
685
686 if (!midMouseButtonDown && e->button() == Qt::MidButton)
687 {
688 y0 = 0.5 * height() - e->y(); //record y pixel coordinate for middle-button zooming
689 midMouseButtonDown = true;
690 }
691
692 if (!mouseButtonDown)
693 {
694 if (e->button() == Qt::LeftButton)
695 {
696 mouseButtonDown = true;
697 }
698
699 //determine RA, Dec of mouse pointer
700 m_MousePoint = projector()->fromScreen(e->pos(), data->lst(), data->geo()->lat());
701 setClickedPoint(&m_MousePoint);
702
703 //Find object nearest to clickedPoint()
704 double maxrad = 5000.0 / Options::zoomFactor();
705 SkyObject *obj = data->skyComposite()->objectNearest(clickedPoint(), maxrad);
706 setClickedObject(obj);
707 if (obj)
708 setClickedPoint(obj);
709
710 switch (e->button())
711 {
712 case Qt::LeftButton:
713 {
714 QString name;
715 if (clickedObject())
716 {
717 name = clickedObject()->translatedLongName();
718 emit objectClicked(clickedObject());
719 }
720 else
721 name = i18n("Empty sky");
722 //kstars->statusBar()->changeItem(name, 0 );
723 kstars->statusBar()->showMessage(name, 0);
724
725 emit positionClicked(&m_MousePoint);
726 }
727
728 break;
729 case Qt::RightButton:
730 if (rulerMode)
731 {
732 // Compute angular distance.
733 slotEndRulerMode();
734 }
735 else
736 {
737 // Show popup menu
738 if (clickedObject())
739 {
740 clickedObject()->showPopupMenu(pmenu, QCursor::pos());
741 }
742 else
743 {
744 pmenu->createEmptyMenu(clickedPoint());
745 pmenu->popup(QCursor::pos());
746 }
747 }
748 break;
749 default:
750 ;
751 }
752 }
753 }
754
mouseDoubleClickEvent(QMouseEvent * e)755 void SkyMap::mouseDoubleClickEvent(QMouseEvent *e)
756 {
757 if (e->button() == Qt::LeftButton && !projector()->unusablePoint(e->pos()))
758 {
759 mouseButtonDown = false;
760 if (e->x() != width() / 2 || e->y() != height() / 2)
761 slotCenter();
762 }
763 }
764
zoomFactor(const int modifier)765 double SkyMap::zoomFactor(const int modifier)
766 {
767 double factor = (modifier & Qt::ControlModifier) ? DZOOM : (Options::zoomScrollFactor() + 1);
768 if (modifier & Qt::ShiftModifier)
769 factor = sqrt(factor);
770 return factor;
771 }
772
zoomInOrMagStep(const int modifier)773 void SkyMap::zoomInOrMagStep(const int modifier)
774 {
775 if (modifier & Qt::AltModifier)
776 incMagLimit(modifier);
777 else
778 setZoomFactor(Options::zoomFactor() * zoomFactor(modifier));
779 }
780
zoomOutOrMagStep(const int modifier)781 void SkyMap::zoomOutOrMagStep(const int modifier)
782 {
783 if (modifier & Qt::AltModifier)
784 decMagLimit(modifier);
785 else
786 setZoomFactor(Options::zoomFactor() / zoomFactor(modifier));
787 }
788
magFactor(const int modifier)789 double SkyMap::magFactor(const int modifier)
790 {
791 double factor = (modifier & Qt::ControlModifier) ? 0.1 : 0.5;
792 if (modifier & Qt::ShiftModifier)
793 factor *= 2.0;
794 return factor;
795 }
796
incMagLimit(const int modifier)797 void SkyMap::incMagLimit(const int modifier)
798 {
799 double limit = 2.222 * log10(static_cast<double>(Options::starDensity())) + 0.35;
800 limit += magFactor(modifier);
801 if (limit > 5.75954)
802 limit = 5.75954;
803 Options::setStarDensity(pow(10, (limit - 0.35) / 2.222));
804 //printf("maglim set to %3.1f\n", limit);
805 forceUpdate();
806 }
807
decMagLimit(const int modifier)808 void SkyMap::decMagLimit(const int modifier)
809 {
810 double limit = 2.222 * log10(static_cast<double>(Options::starDensity())) + 0.35;
811 limit -= magFactor(modifier);
812 if (limit < 1.18778)
813 limit = 1.18778;
814 Options::setStarDensity(pow(10, (limit - 0.35) / 2.222));
815 //printf("maglim set to %3.1f\n", limit);
816 forceUpdate();
817 }
818