moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / skymapevents.cpp
blob51a7cfc6f66f0076c6082fb4a5c01969642bafd8
1 /***************************************************************************
2 skymapevents.cpp - K Desktop Planetarium
3 -------------------
4 begin : Sat Feb 10 2001
5 copyright : (C) 2001 by Jason Harris
6 email : jharris@30doradus.org
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 //This file contains Event handlers for the SkyMap class.
20 #include <stdlib.h>
21 #include <math.h> //using fabs()
23 #include <qcursor.h>
24 #include <qpainter.h>
25 #include <qfile.h>
27 #include <kiconloader.h>
28 #include <kstatusbar.h>
29 #include <kshortcut.h> //KKey class
31 #include "skymap.h"
32 #include "Options.h"
33 #include "kstars.h"
34 #include "kstarsdata.h"
35 #include "ksutils.h"
36 #include "simclock.h"
37 #include "infoboxes.h"
38 #include "ksfilereader.h"
39 #include "kspopupmenu.h"
40 #include "ksmoon.h"
42 void SkyMap::resizeEvent( QResizeEvent * )
44 computeSkymap = true; // skymap must be new computed
45 if ( testWState(WState_AutoMask) ) updateMask();
47 // avoid phantom positions of infoboxes
48 if ( ksw && ( isVisible() || width() == ksw->width() || height() == ksw->height() ) ) {
49 infoBoxes()->resize( width(), height() );
51 sky->resize( width(), height() );
54 void SkyMap::keyPressEvent( QKeyEvent *e ) {
55 QString s;
56 bool arrowKeyPressed( false );
57 bool shiftPressed( false );
58 float step = 1.0;
59 if ( e->state() & ShiftButton ) { step = 10.0; shiftPressed = true; }
61 //If the DCOP resume key was pressed, we process it here
62 if ( ! data->resumeKey.isNull() && e->key() == data->resumeKey.keyCodeQt() ) {
63 //kdDebug() << "resumeKey pressed; resuming DCOP." << endl;
64 ksw->resumeDCOP();
65 return;
68 switch ( e->key() ) {
69 case Key_Left :
70 if ( Options::useAltAz() ) {
71 focus()->setAz( dms( focus()->az()->Degrees() - step * MINZOOM/Options::zoomFactor() ).reduce() );
72 focus()->HorizontalToEquatorial( data->LST, data->geo()->lat() );
73 } else {
74 focus()->setRA( focus()->ra()->Hours() + 0.05*step * MINZOOM/Options::zoomFactor() );
75 focus()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
78 arrowKeyPressed = true;
79 slewing = true;
80 ++scrollCount;
81 break;
83 case Key_Right :
84 if ( Options::useAltAz() ) {
85 focus()->setAz( dms( focus()->az()->Degrees() + step * MINZOOM/Options::zoomFactor() ).reduce() );
86 focus()->HorizontalToEquatorial( data->LST, data->geo()->lat() );
87 } else {
88 focus()->setRA( focus()->ra()->Hours() - 0.05*step * MINZOOM/Options::zoomFactor() );
89 focus()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
92 arrowKeyPressed = true;
93 slewing = true;
94 ++scrollCount;
95 break;
97 case Key_Up :
98 if ( Options::useAltAz() ) {
99 focus()->setAlt( focus()->alt()->Degrees() + step * MINZOOM/Options::zoomFactor() );
100 if ( focus()->alt()->Degrees() > 90.0 ) focus()->setAlt( 90.0 );
101 focus()->HorizontalToEquatorial( data->LST, data->geo()->lat() );
102 } else {
103 focus()->setDec( focus()->dec()->Degrees() + step * MINZOOM/Options::zoomFactor() );
104 if (focus()->dec()->Degrees() > 90.0) focus()->setDec( 90.0 );
105 focus()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
108 arrowKeyPressed = true;
109 slewing = true;
110 ++scrollCount;
111 break;
113 case Key_Down:
114 if ( Options::useAltAz() ) {
115 focus()->setAlt( focus()->alt()->Degrees() - step * MINZOOM/Options::zoomFactor() );
116 if ( focus()->alt()->Degrees() < -90.0 ) focus()->setAlt( -90.0 );
117 focus()->HorizontalToEquatorial( data->LST, data->geo()->lat() );
118 } else {
119 focus()->setDec( focus()->dec()->Degrees() - step * MINZOOM/Options::zoomFactor() );
120 if (focus()->dec()->Degrees() < -90.0) focus()->setDec( -90.0 );
121 focus()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
124 arrowKeyPressed = true;
125 slewing = true;
126 ++scrollCount;
127 break;
129 case Key_Plus: //Zoom in
130 case Key_Equal:
131 if ( ksw ) ksw->slotZoomIn();
132 break;
134 case Key_Minus: //Zoom out
135 case Key_Underscore:
136 if ( ksw ) ksw->slotZoomOut();
137 break;
139 //In the following cases, we set slewing=true in order to disengage tracking
140 case Key_N: //center on north horizon
141 stopTracking();
142 setDestinationAltAz( 15.0, 0.0001 );
143 break;
145 case Key_E: //center on east horizon
146 stopTracking();
147 setDestinationAltAz( 15.0, 90.0 );
148 break;
150 case Key_S: //center on south horizon
151 stopTracking();
152 setDestinationAltAz( 15.0, 180.0 );
153 break;
155 case Key_W: //center on west horizon
156 stopTracking();
157 setDestinationAltAz( 15.0, 270.0 );
158 break;
160 case Key_Z: //center on Zenith
161 stopTracking();
162 setDestinationAltAz( 90.0, focus()->az()->Degrees() );
163 break;
165 case Key_0: //center on Sun
166 setClickedObject( data->PCat->findByName("Sun") );
167 setClickedPoint( clickedObject() );
168 slotCenter();
169 break;
171 case Key_1: //center on Mercury
172 setClickedObject( data->PCat->findByName("Mercury") );
173 setClickedPoint( clickedObject() );
174 slotCenter();
175 break;
177 case Key_2: //center on Venus
178 setClickedObject( data->PCat->findByName("Venus") );
179 setClickedPoint( clickedObject() );
180 slotCenter();
181 break;
183 case Key_3: //center on Moon
184 setClickedObject( data->Moon );
185 setClickedPoint( clickedObject() );
186 slotCenter();
187 break;
189 case Key_4: //center on Mars
190 setClickedObject( data->PCat->findByName("Mars") );
191 setClickedPoint( clickedObject() );
192 slotCenter();
193 break;
195 case Key_5: //center on Jupiter
196 setClickedObject( data->PCat->findByName("Jupiter") );
197 setClickedPoint( clickedObject() );
198 slotCenter();
199 break;
201 case Key_6: //center on Saturn
202 setClickedObject( data->PCat->findByName("Saturn") );
203 setClickedPoint( clickedObject() );
204 slotCenter();
205 break;
207 case Key_7: //center on Uranus
208 setClickedObject( data->PCat->findByName("Uranus") );
209 setClickedPoint( clickedObject() );
210 slotCenter();
211 break;
213 case Key_8: //center on Neptune
214 setClickedObject( data->PCat->findByName("Neptune") );
215 setClickedPoint( clickedObject() );
216 slotCenter();
217 break;
219 case Key_9: //center on Pluto
220 setClickedObject( data->PCat->findByName("Pluto") );
221 setClickedPoint( clickedObject() );
222 slotCenter();
223 break;
225 case Key_BracketLeft: // Begin measuring angular distance
226 if ( !isAngleMode() ) {
227 slotBeginAngularDistance();
230 break;
232 case Key_BracketRight: // End measuring angular distance
233 if ( isAngleMode() ) {
234 slotEndAngularDistance();
237 break;
239 case Key_Escape: // Cancel angular distance measurement
240 if (isAngleMode() ) {
241 slotCancelAngularDistance();
243 break;
245 case Key_Comma: //advance one step backward in time
246 case Key_Less:
247 if ( data->clock()->isActive() ) data->clock()->stop();
248 data->clock()->setScale( -1.0 * data->clock()->scale() ); //temporarily need negative time step
249 data->clock()->manualTick( true );
250 data->clock()->setScale( -1.0 * data->clock()->scale() ); //reset original sign of time step
251 update();
252 kapp->processEvents();
253 break;
255 case Key_Period: //advance one step forward in time
256 case Key_Greater:
257 if ( data->clock()->isActive() ) data->clock()->stop();
258 data->clock()->manualTick( true );
259 update();
260 kapp->processEvents();
261 break;
263 //FIXME: Uncomment after feature thaw!
264 // case Key_C: //Center clicked object object
265 // if ( clickedObject() ) slotCenter();
266 // break;
268 case Key_D: //Details window for Clicked/Centered object
269 if ( shiftPressed ) setClickedObject( focusObject() );
270 if ( clickedObject() ) slotDetail();
271 break;
273 case Key_P: //Show Popup menu for Clicked/Centered object
274 if ( shiftPressed ) setClickedObject( focusObject() );
275 if ( clickedObject() )
276 clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
277 break;
279 case Key_O: //Add object to Observing List
280 if ( shiftPressed ) setClickedObject( focusObject() );
281 if ( clickedObject() )
282 ksw->observingList()->slotAddObject();
283 break;
285 case Key_L: //Toggle User label on Clicked/Centered object
286 if ( shiftPressed ) setClickedObject( focusObject() );
287 if ( clickedObject() ) {
288 if ( isObjectLabeled( clickedObject() ) )
289 slotRemoveObjectLabel();
290 else
291 slotAddObjectLabel();
293 break;
295 case Key_T: //Toggle planet trail on Clicked/Centered object (if solsys)
296 if ( shiftPressed ) setClickedObject( focusObject() );
297 if ( clickedObject() && clickedObject()->isSolarSystem() ) {
298 if ( ((KSPlanetBase*)clickedObject())->hasTrail() )
299 slotRemovePlanetTrail();
300 else
301 slotAddPlanetTrail();
303 break;
307 //TIMING
309 case Key_G: //loop through all cities
312 QFile file;
313 if ( KSUtils::openDataFile( file, "Cities.dat" ) ) {
314 KSFileReader fileReader( file );
315 int nCount = 0;
316 while (fileReader.hasMoreLines()) {
317 QString line = fileReader.readLine();
318 nCount++;
319 kdDebug() << "Line " << nCount << " : " << line;
323 QTime t1;
324 t1.start();
325 for (int i=0;i<10;i++) {
326 if ( KSUtils::openDataFile( file, "Cities.dat" ) ) {
327 QString sAll( file.readAll() );
328 QStringList lines = QStringList::split( "\n", sAll );
329 int nSize = lines.size();
330 for ( int i=0; i<nSize; i++ ) {
331 QString& line = lines[i];
333 file.close();
336 kdDebug() << "time taken for reading city data via read all (10 times): (msec): " << t1.elapsed() << endl;
338 QTime t2;
339 t2.start();
340 for (int i=0;i<10;i++) {
341 if ( KSUtils::openDataFile( file, "Cities.dat" ) ) {
342 QTextStream stream( &file );
343 while ( !stream.eof() ) {
344 QString line = stream.readLine();
346 file.close();
349 kdDebug() << "time taken for reading city data old code (10 times): (msec): " << t2.elapsed() << endl;
351 QTime t3;
352 t3.start();
353 for (int i=0;i<1;i++) {
354 if ( KSUtils::openDataFile( file, "ngcic.dat" ) ) {
355 QString sAll( file.readAll() );
356 QStringList lines = QStringList::split( "\n", sAll );
357 int nSize = lines.size();
358 for ( int i=0; i<nSize; i++ ) {
359 QString& line = lines[i];
361 file.close();
364 kdDebug() << "time taken for reading deep sky data via read all (1 times): (msec): " << t3.elapsed() << endl;
366 QTime t4;
367 t4.start();
368 for (int i=0;i<1;i++) {
369 if ( KSUtils::openDataFile( file, "ngcic.dat" ) ) {
370 QTextStream stream( &file );
371 while ( !stream.eof() ) {
372 QString line = stream.readLine();
374 file.close();
377 kdDebug() << "time taken for reading deep sky data old code (1 times): (msec): " << t4.elapsed() << endl;
379 break;
383 //END_TIMING
386 setOldFocus( focus() );
387 oldfocus()->setAz( focus()->az()->Degrees() );
388 oldfocus()->setAlt( focus()->alt()->Degrees() );
390 double dHA = data->LST->Hours() - focus()->ra()->Hours();
391 while ( dHA < 0.0 ) dHA += 24.0;
392 data->HourAngle->setH( dHA );
394 if ( arrowKeyPressed ) {
395 infoBoxes()->focusObjChanged( i18n( "nothing" ) );
396 stopTracking();
398 if ( scrollCount > 10 ) {
399 setDestination( focus() );
400 scrollCount = 0;
404 forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work.
407 void SkyMap::stopTracking() {
408 if ( ksw && Options::isTracking() ) ksw->slotTrack();
411 void SkyMap::keyReleaseEvent( QKeyEvent *e ) {
412 switch ( e->key() ) {
413 case Key_Left : //no break; continue to Key_Down
414 case Key_Right : //no break; continue to Key_Down
415 case Key_Up : //no break; continue to Key_Down
416 case Key_Down :
417 slewing = false;
418 scrollCount = 0;
420 if ( Options::useAltAz() )
421 setDestinationAltAz( focus()->alt()->Degrees(), focus()->az()->Degrees() );
422 else
423 setDestination( focus() );
425 showFocusCoords();
426 forceUpdate(); // Need a full update to draw faint objects that are not drawn while slewing.
427 break;
431 void SkyMap::mouseMoveEvent( QMouseEvent *e ) {
432 if ( Options::useHoverLabel() ) {
433 //First of all, if the transientObject() pointer is not NULL, then
434 //we just moved off of a hovered object. Begin fading the label.
435 if ( transientObject() && ! TransientTimer.isActive() ) {
436 fadeTransientLabel();
439 //Start a single-shot timer to monitor whether we are currently hovering.
440 //The idea is that whenever a moveEvent occurs, the timer is reset. It
441 //will only timeout if there are no move events for HOVER_INTERVAL ms
442 HoverTimer.start( HOVER_INTERVAL, true );
445 //Are we dragging an infoBox?
446 if ( infoBoxes()->dragBox( e ) ) {
447 update();
448 return;
451 //Are we defining a ZoomRect?
452 if ( ZoomRect.center().x() > 0 && ZoomRect.center().y() > 0 ) {
453 //cancel operation if the user let go of CTRL
454 if ( !( e->state() & ControlButton ) ) {
455 ZoomRect = QRect(); //invalidate ZoomRect
456 update();
457 } else {
458 //Resize the rectangle so that it passes through the cursor position
459 QPoint pcenter = ZoomRect.center();
460 int dx = abs(e->x() - pcenter.x());
461 int dy = abs(e->y() - pcenter.y());
462 if ( dx == 0 || float(dy)/float(dx) > float(height())/float(width()) ) {
463 //Size rect by height
464 ZoomRect.setHeight( 2*dy );
465 ZoomRect.setWidth( 2*dy*width()/height() );
466 } else {
467 //Size rect by height
468 ZoomRect.setWidth( 2*dx );
469 ZoomRect.setHeight( 2*dx*height()/width() );
471 ZoomRect.moveCenter( pcenter ); //reset center
473 update();
474 return;
478 double dx = ( 0.5*width() - e->x() )/Options::zoomFactor();
479 double dy = ( 0.5*height() - e->y() )/Options::zoomFactor();
480 double dyPix = 0.5*height() - e->y();
482 if (unusablePoint (dx, dy)) return; // break if point is unusable
484 //determine RA, Dec of mouse pointer
485 setMousePoint( dXdYToRaDec( dx, dy, Options::useAltAz(), data->LST, data->geo()->lat(), Options::useRefraction() ) );
486 mousePoint()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
489 if ( midMouseButtonDown ) { //zoom according to y-offset
490 float yoff = dyPix - y0;
492 if (yoff > 10 ) {
493 y0 = dyPix;
494 if ( ksw ) ksw->slotZoomIn();
496 if (yoff < -10 ) {
497 y0 = dyPix;
498 if ( ksw ) ksw->slotZoomOut();
502 if ( mouseButtonDown ) {
503 // set the mouseMoveCursor and set slewing=true, if they are not set yet
504 if (!mouseMoveCursor) setMouseMoveCursor();
505 if (!slewing) {
506 slewing = true;
507 infoBoxes()->focusObjChanged( i18n( "nothing" ) );
508 if ( ksw && Options::isTracking() ) ksw->slotTrack(); //toggle tracking off
511 //Update focus such that the sky coords at mouse cursor remain approximately constant
512 if ( Options::useAltAz() ) {
513 mousePoint()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
514 clickedPoint()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
515 dms dAz = mousePoint()->az()->Degrees() - clickedPoint()->az()->Degrees();
516 dms dAlt = mousePoint()->alt()->Degrees() - clickedPoint()->alt()->Degrees();
517 focus()->setAz( focus()->az()->Degrees() - dAz.Degrees() ); //move focus in opposite direction
518 focus()->setAlt( focus()->alt()->Degrees() - dAlt.Degrees() );
520 if ( focus()->alt()->Degrees() >90.0 ) focus()->setAlt( 90.0 );
521 if ( focus()->alt()->Degrees() <-90.0 ) focus()->setAlt( -90.0 );
522 focus()->setAz( focus()->az()->reduce() );
523 focus()->HorizontalToEquatorial( data->LST, data->geo()->lat() );
524 } else {
525 dms dRA = mousePoint()->ra()->Degrees() - clickedPoint()->ra()->Degrees();
526 dms dDec = mousePoint()->dec()->Degrees() - clickedPoint()->dec()->Degrees();
527 focus()->setRA( focus()->ra()->Hours() - dRA.Hours() ); //move focus in opposite direction
528 focus()->setDec( focus()->dec()->Degrees() - dDec.Degrees() );
530 if ( focus()->dec()->Degrees() >90.0 ) focus()->setDec( 90.0 );
531 if ( focus()->dec()->Degrees() <-90.0 ) focus()->setDec( -90.0 );
532 focus()->setRA( focus()->ra()->reduce() );
533 focus()->EquatorialToHorizontal( data->LST, data->geo()->lat() );
536 ++scrollCount;
537 if ( scrollCount > 4 ) {
538 showFocusCoords();
539 scrollCount = 0;
542 setOldFocus( focus() );
544 double dHA = data->LST->Hours() - focus()->ra()->Hours();
545 while ( dHA < 0.0 ) dHA += 24.0;
546 data->HourAngle->setH( dHA );
548 //redetermine RA, Dec of mouse pointer, using new focus
549 setMousePoint( dXdYToRaDec( dx, dy, Options::useAltAz(), data->LST, data->geo()->lat(), Options::useRefraction() ) );
550 setClickedPoint( mousePoint() );
552 forceUpdate(); // must be new computed
553 } else {
555 if ( ksw ) {
556 QString sX, sY, s;
557 sX = mousePoint()->az()->toDMSString(true); //true = force +/- symbol
558 sY = mousePoint()->alt()->toDMSString(true); //true = force +/- symbol
559 s = sX + ", " + sY;
560 ksw->statusBar()->changeItem( s, 1 );
562 sX = mousePoint()->ra()->toHMSString();
563 sY = mousePoint()->dec()->toDMSString(true); //true = force +/- symbol
564 s = sX + ", " + sY;
565 ksw->statusBar()->changeItem( s, 2 );
570 void SkyMap::wheelEvent( QWheelEvent *e ) {
571 if ( ksw && e->delta() > 0 ) ksw->slotZoomIn();
572 else if ( ksw ) ksw->slotZoomOut();
575 void SkyMap::mouseReleaseEvent( QMouseEvent * ) {
576 if ( infoBoxes()->unGrabBox() ) {
577 update();
578 return;
581 if ( ZoomRect.isValid() ) {
582 //Zoom in on center of Zoom Circle, by a factor equal to the ratio
583 //of the sky pixmap's width to the Zoom Circle's diameter
584 float factor = float(width()) / float(ZoomRect.width());
586 double dx = ( 0.5*width() - ZoomRect.center().x() )/Options::zoomFactor();
587 double dy = ( 0.5*height() - ZoomRect.center().y() )/Options::zoomFactor();
589 SkyPoint newcenter = dXdYToRaDec( dx, dy, Options::useAltAz(), data->LST, data->geo()->lat(), Options::useRefraction() );
590 setClickedPoint( &newcenter );
591 setClickedObject( NULL );
592 setFocusObject( NULL );
593 setFocus( &newcenter );
594 setDestination( &newcenter );
595 setOldFocus( &newcenter );
596 ksw->zoom( Options::zoomFactor() * factor );
598 setDefaultMouseCursor();
599 ZoomRect = QRect(); //invalidate ZoomRect
600 forceUpdate();
601 } else {
602 setDefaultMouseCursor();
603 ZoomRect = QRect(); //just in case user Ctrl+clicked + released w/o dragging...
606 if (mouseMoveCursor) setDefaultMouseCursor(); // set default cursor
607 if (mouseButtonDown) { //false if double-clicked, because it's unset there.
608 mouseButtonDown = false;
609 if ( slewing ) {
610 slewing = false;
612 if ( Options::useAltAz() )
613 setDestinationAltAz( focus()->alt()->Degrees(), focus()->az()->Degrees() );
614 else
615 setDestination( focus() );
618 setOldFocus( focus() );
619 forceUpdate(); // is needed because after moving the sky not all stars are shown
621 if ( midMouseButtonDown ) midMouseButtonDown = false; // if middle button was pressed unset here
623 scrollCount = 0;
626 void SkyMap::mousePressEvent( QMouseEvent *e ) {
627 //did we Grab an infoBox?
628 if ( e->button() == LeftButton && infoBoxes()->grabBox( e ) ) {
629 update(); //refresh without redrawing skymap
630 return;
633 if ( (e->state() & ControlButton) && (e->button() == LeftButton) ) {
634 ZoomRect.moveCenter( e->pos() );
635 setZoomMouseCursor();
636 update(); //refresh without redrawing skymap
637 return;
640 // if button is down and cursor is not moved set the move cursor after 500 ms
641 QTimer t;
642 t.singleShot (500, this, SLOT (setMouseMoveCursor()));
644 double dx = ( 0.5*width() - e->x() )/Options::zoomFactor();
645 double dy = ( 0.5*height() - e->y() )/Options::zoomFactor();
646 if (unusablePoint (dx, dy)) return; // break if point is unusable
648 if ( !midMouseButtonDown && e->button() == MidButton ) {
649 y0 = 0.5*height() - e->y(); //record y pixel coordinate for middle-button zooming
650 midMouseButtonDown = true;
653 if ( !mouseButtonDown ) {
654 if ( e->button()==LeftButton ) {
655 mouseButtonDown = true;
656 scrollCount = 0;
659 //determine RA, Dec of mouse pointer
660 setMousePoint( dXdYToRaDec( dx, dy, Options::useAltAz(),
661 data->LST, data->geo()->lat(), Options::useRefraction() ) );
662 setClickedPoint( mousePoint() );
664 //Find object nearest to clickedPoint()
665 setClickedObject( objectNearest( clickedPoint() ) );
667 if ( clickedObject() ) {
668 setClickedPoint( clickedObject() );
670 if ( e->button() == RightButton ) {
671 clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
674 if ( ksw && e->button() == LeftButton ) {
675 ksw->statusBar()->changeItem( clickedObject()->translatedLongName(), 0 );
677 } else {
678 //Empty sky selected. If left-click, display "nothing" in the status bar.
679 //If right-click, open "empty" popup menu.
680 setClickedObject( NULL );
682 switch (e->button()) {
683 case LeftButton:
684 if ( ksw ) ksw->statusBar()->changeItem( i18n( "Empty sky" ), 0 );
685 break;
686 case RightButton:
688 SkyObject *nullObj = new SkyObject( SkyObject::TYPE_UNKNOWN, clickedPoint()->ra()->Hours(), clickedPoint()->dec()->Degrees() );
689 pmenu->createEmptyMenu( nullObj );
690 delete nullObj;
692 pmenu->popup( QCursor::pos() );
693 break;
696 default:
697 break;
703 void SkyMap::mouseDoubleClickEvent( QMouseEvent *e ) {
704 //Was the event inside an infoBox? If so, shade the box.
705 if ( e->button() == LeftButton ) {
706 if ( infoBoxes()->shadeBox( e ) ) {
707 update();
708 return;
711 double dx = ( 0.5*width() - e->x() )/Options::zoomFactor();
712 double dy = ( 0.5*height() - e->y() )/Options::zoomFactor();
713 if (unusablePoint (dx, dy)) return; // break if point is unusable
715 if (mouseButtonDown ) mouseButtonDown = false;
716 if ( dx != 0.0 || dy != 0.0 ) slotCenter();
720 void SkyMap::paintEvent( QPaintEvent * )
722 //If computeSkymap is false, then we just refresh the window using the stored sky pixmap
723 //and draw the "overlays" on top. This lets us update the overlay information rapidly
724 //without needing to recompute the entire skymap.
725 //use update() to trigger this "short" paint event; to force a full "recompute"
726 //of the skymap, use forceUpdate().
727 if (!computeSkymap)
729 QPixmap *sky2 = new QPixmap( *sky );
730 drawOverlays( sky2 );
731 bitBlt( this, 0, 0, sky2 );
732 delete sky2;
733 return ; // exit because the pixmap is repainted and that's all what we want
736 QPainter psky;
737 setMapGeometry();
739 //checkSlewing combines the slewing flag (which is true when the display is actually in motion),
740 //the hideOnSlew option (which is true if slewing should hide objects),
741 //and clockSlewing (which is true if the timescale exceeds Options::slewTimeScale)
742 bool checkSlewing = ( ( slewing || ( clockSlewing && data->clock()->isActive() ) )
743 && Options::hideOnSlew() );
745 //shortcuts to inform wheter to draw different objects
746 bool drawPlanets( Options::showPlanets() && !(checkSlewing && Options::hidePlanets() ) );
747 bool drawMW( Options::showMilkyWay() && !(checkSlewing && Options::hideMilkyWay() ) );
748 bool drawCNames( Options::showCNames() && !(checkSlewing && Options::hideCNames() ) );
749 bool drawCLines( Options::showCLines() &&!(checkSlewing && Options::hideCLines() ) );
750 bool drawCBounds( Options::showCBounds() &&!(checkSlewing && Options::hideCBounds() ) );
751 bool drawGrid( Options::showGrid() && !(checkSlewing && Options::hideGrid() ) );
753 psky.begin( sky );
754 psky.fillRect( 0, 0, width(), height(), QBrush( data->colorScheme()->colorNamed( "SkyColor" ) ) );
756 if ( drawMW ) drawMilkyWay( psky );
757 if ( drawGrid ) drawCoordinateGrid( psky );
759 if ( drawCBounds ) drawConstellationBoundaries( psky );
760 if ( drawCLines ) drawConstellationLines( psky );
761 if ( drawCNames ) drawConstellationNames( psky );
763 if ( Options::showEquator() ) drawEquator( psky );
764 if ( Options::showEcliptic() ) drawEcliptic( psky );
766 //drawing to screen, so leave scale parameter at its default value of 1.0
767 drawStars( psky );
768 drawDeepSkyObjects( psky );
769 drawSolarSystem( psky, drawPlanets );
770 drawAttachedLabels( psky );
771 drawHorizon( psky );
773 //Finish up
774 psky.end();
776 QPixmap *sky2 = new QPixmap( *sky );
777 drawOverlays( sky2 );
778 bitBlt( this, 0, 0, sky2 );
779 delete sky2;
781 computeSkymap = false; // use forceUpdate() to compute new skymap else old pixmap will be shown