• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
  • tools
skycalendar.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  skycalendar.cpp - description
3  -------------------
4  begin : Wed Jul 16 2008
5  copyright : (C) 2008 by Jason Harris
6  email : kstars@30doradus.org
7  ***************************************************************************/
8 
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  ***************************************************************************/
17 
18 #include "skycalendar.h"
19 
20 #include <QDesktopWidget>
21 #include <QPixmap>
22 #include <QPainter>
23 #include <QPrinter>
24 #include <QPrintDialog>
25 #include <QFontInfo>
26 #include <kdeprintdialog.h>
27 #include <kdebug.h>
28 #include <KPlotObject>
29 #include <KPushButton>
30 
31 #include "calendarwidget.h"
32 #include "geolocation.h"
33 #include "dialogs/locationdialog.h"
34 #include "kstarsdatetime.h"
35 #include "kstarsdata.h"
36 #include "skyobjects/ksplanet.h"
37 #include "skycomponents/skymapcomposite.h"
38 
39 namespace {
40  // convert time to decimal hours since midnight
41  float timeToHours(QTime t) {
42  float h = t.secsTo(QTime()) * -24.0 / 86400.0;
43  if( h > 12.0 )
44  h -= 24.0;
45  return h;
46  }
47 
48  // Check that axis has been crossed
49  inline bool isAxisCrossed(const QVector<QPointF>& vec, int i) {
50  return i > 0 && vec.at(i-1).x() * vec.at(i).x() <= 0;
51  }
52  // Check that we are at maximum
53  inline bool isAtExtremum(const QVector<QPointF>& vec, int i) {
54  return
55  i > 0 && i < vec.size() - 1 &&
56  (vec.at(i-1).x() - vec.at(i).x()) * (vec.at(i).x() - vec.at(i+1).x()) < 0;
57  }
58 }
59 
60 SkyCalendarUI::SkyCalendarUI( QWidget *parent )
61  : QFrame( parent )
62 {
63  setupUi( this );
64 }
65 
66 SkyCalendar::SkyCalendar( QWidget *parent )
67  : KDialog( parent )
68 {
69  scUI = new SkyCalendarUI( this );
70  setMainWidget( scUI );
71 
72  geo = KStarsData::Instance()->geo();
73 
74  setCaption( i18n( "Sky Calendar" ) );
75  setButtons( KDialog::User1 | KDialog::Close );
76  setModal( false );
77 
78  //Adjust minimum size for small screens:
79  if ( QApplication::desktop()->availableGeometry().height() <= scUI->CalendarView->height() ) {
80  scUI->CalendarView->setMinimumSize( 400, 600 );
81  }
82 
83  scUI->CalendarView->setShowGrid( false );
84  scUI->Year->setValue( KStarsData::Instance()->lt().date().year() );
85 
86  scUI->LocationButton->setText( geo->fullName() );
87  setButtonGuiItem( KDialog::User1, KGuiItem( i18n("&Print..."), "document-print", i18n("Print the Sky Calendar") ) );
88 
89  scUI->CalendarView->setHorizon();
90 
91  connect( scUI->CreateButton, SIGNAL(clicked()), this, SLOT(slotFillCalendar()) );
92  connect( scUI->LocationButton, SIGNAL(clicked()), this, SLOT(slotLocation()) );
93  connect( this, SIGNAL( user1Clicked() ), this, SLOT( slotPrint() ) );
94 }
95 
96 SkyCalendar::~SkyCalendar() {
97 }
98 
99 int SkyCalendar::year() { return scUI->Year->value(); }
100 
101 void SkyCalendar::slotFillCalendar() {
102  scUI->CalendarView->resetPlot();
103  scUI->CalendarView->setHorizon();
104 
105  if ( scUI->checkBox_Mercury->isChecked() )
106  addPlanetEvents( KSPlanetBase::MERCURY );
107  if ( scUI->checkBox_Venus->isChecked() )
108  addPlanetEvents( KSPlanetBase::VENUS );
109  if ( scUI->checkBox_Mars->isChecked() )
110  addPlanetEvents( KSPlanetBase::MARS );
111  if ( scUI->checkBox_Jupiter->isChecked() )
112  addPlanetEvents( KSPlanetBase::JUPITER );
113  if ( scUI->checkBox_Saturn->isChecked() )
114  addPlanetEvents( KSPlanetBase::SATURN );
115  if ( scUI->checkBox_Uranus->isChecked() )
116  addPlanetEvents( KSPlanetBase::URANUS );
117  if ( scUI->checkBox_Neptune->isChecked() )
118  addPlanetEvents( KSPlanetBase::NEPTUNE );
119  if ( scUI->checkBox_Pluto->isChecked() )
120  addPlanetEvents( KSPlanetBase::PLUTO );
121 
122  scUI->CalendarView->update();
123 }
124 
125 // FIXME: For the time being, adjust with dirty, cluttering labels that don't align to the line
126 /*
127 void SkyCalendar::drawEventLabel( float x1, float y1, float x2, float y2, QString LabelText ) {
128  QFont origFont = p->font();
129  p->setFont( QFont( "Bitstream Vera", 10 ) );
130 
131  int textFlags = Qt::AlignCenter; // TODO: See if Qt::SingleLine flag works better
132  QFontMetricsF fm( p->font(), p->device() );
133 
134  QRectF LabelRect = fm.boundingRect( QRectF(0,0,1,1), textFlags, LabelText );
135  QPointF LabelPoint = scUI->CalendarView->mapToWidget( QPointF( x, y ) );
136 
137  float LabelAngle = atan2( y2 - y1, x2 - x1 )/dms::DegToRad;
138 
139  p->save();
140  p->translate( LabelPoint );
141  p->rotate( LabelAngle );
142  p->drawText( LabelRect, textFlags, LabelText );
143  p->restore();
144 
145  p->setFont( origFont );
146 }
147 */
148 
149 void SkyCalendar::addPlanetEvents( int nPlanet ) {
150  KSPlanetBase *ksp = KStarsData::Instance()->skyComposite()->planet( nPlanet );
151  QColor pColor = ksp->color();
152  QVector<QPointF> vRise, vSet, vTransit;
153 
154  for( KStarsDateTime kdt( QDate( year(), 1, 1 ), QTime( 12, 0, 0 ) );
155  kdt.date().year() == year();
156  kdt = kdt.addDays( scUI->spinBox_Interval->value() ) )
157  {
158  float rTime, sTime, tTime;
159 
160  //Compute rise/set/transit times. If they occur before noon,
161  //recompute for the following day
162  QTime tmp_rTime = ksp->riseSetTime( kdt, geo, true, true ); //rise time, exact
163  QTime tmp_sTime = ksp->riseSetTime( kdt, geo, false, true ); //set time, exact
164  QTime tmp_tTime = ksp->transitTime( kdt, geo );
165  QTime midday( 12, 0, 0 );
166 
167  // NOTE: riseSetTime should be fix now, this test is no longer necessary
168  if ( tmp_rTime == tmp_sTime ) {
169  tmp_rTime = QTime();
170  tmp_sTime = QTime();
171  }
172 
173  if ( tmp_rTime.isValid() && tmp_sTime.isValid() ) {
174  rTime = tmp_rTime.secsTo( midday ) * 24.0 / 86400.0;
175  sTime = tmp_sTime.secsTo( midday ) * 24.0 / 86400.0;
176 
177  if ( tmp_rTime <= midday )
178  rTime = 12.0 - rTime;
179  else
180  rTime = -12.0 - rTime;
181 
182  if ( tmp_sTime <= midday )
183  sTime = 12.0 - sTime;
184  else
185  sTime = -12.0 - sTime;
186  } else {
187  if ( ksp->transitAltitude( kdt, geo ).degree() > 0 ) {
188  rTime = -24.0;
189  sTime = 24.0;
190  } else {
191  rTime = 24.0;
192  sTime = -24.0;
193  }
194  }
195 
196  tTime = tmp_tTime.secsTo( midday ) * 24.0 / 86400.0;
197  if ( tmp_tTime <= midday )
198  tTime = 12.0 - tTime;
199  else
200  tTime = -12.0 - tTime;
201 
202  float dy = kdt.date().daysInYear() - kdt.date().dayOfYear();
203  vRise << QPointF( rTime, dy );
204  vSet << QPointF( sTime, dy );
205  vTransit << QPointF( tTime, dy );
206  }
207 
208  //Now, find continuous segments in each QVector and add each segment
209  //as a separate KPlotObject
210 
211  KPlotObject *oRise = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
212  KPlotObject *oSet = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
213  KPlotObject *oTransit = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
214  bool needRiseLabel = true;
215  bool needSetLabel = true;
216  bool needTransertLabel = true;
217  QString label;
218 
219  for ( int i=0; i<vRise.size(); ++i ) {
220  /* if rise time is set under -23.0 or above 23.0, it means the planet never rise or set,
221  * we add the current KPlotObject to CalendarView and create a new one. */
222  if ( vRise.at( i ).x() > -23.0 && vRise.at( i ).x() < 23.0 ) {
223  /* If the difference between to points is greater than 6 hours,
224  * we consider the line continues on the other side of the view.
225  * Add the current KPlotObject to CalendarView and create a new one. */
226  if ( i > 0 && fabs( vRise.at( i ).x() - vRise.at( i-1 ).x() ) > 6.0 ) {
227  scUI->CalendarView->addPlotObject( oRise );
228  oRise = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
229  needRiseLabel = true;
230  }
231  // Set label if the line is on the night area, and if it needs one.
232  if ( needRiseLabel
233  && vRise.at(i).x() > scUI->CalendarView->getSetTime( i )
234  && vRise.at(i).x() < scUI->CalendarView->getRiseTime( i ) ) {
235  label = i18nc( "A planet rises from the horizon", "%1 rises", ksp->name() );
236  needRiseLabel = false;
237  } else
238  label = QString();
239  /* When the line is over day area, we set needRiseLabel to true, so, the next
240  * time the line pass over the night area, a label will be draw. */
241  if ( vRise.at(i).x() >= scUI->CalendarView->getRiseTime( i ) )
242  needRiseLabel = true;
243  // Add the current point to KPlotObject
244  oRise->addPoint( vRise.at(i), label );
245  } else {
246  scUI->CalendarView->addPlotObject( oRise );
247  oRise = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
248  needRiseLabel = true;
249  }
250 
251  // Same process for set time
252  if ( vSet.at( i ).x() > -23.0 && vSet.at( i ).x() < 23.0) {
253  if ( i > 0 && fabs( vSet.at( i ).x() - vSet.at( i-1 ).x() ) > 6.0 ) {
254  scUI->CalendarView->addPlotObject( oSet );
255  oSet = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
256  needSetLabel = true;
257  }
258  if ( needSetLabel && vSet.at(i).x() > scUI->CalendarView->getSetTime( i ) && vSet.at(i).x() < scUI->CalendarView->getRiseTime( i ) ){
259  label = i18nc( "A planet sets from the horizon", "%1 sets", ksp->name() );
260  needSetLabel = false;
261  } else
262  label = QString();
263  if ( vSet.at(i).x() <= scUI->CalendarView->getSetTime( i ) )
264  needSetLabel = true;
265  oSet->addPoint( vSet.at(i), label );
266  } else {
267  scUI->CalendarView->addPlotObject( oSet );
268  oSet = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
269  needSetLabel = true;
270  }
271 
272  // Same process for transit time
273  if ( vTransit.at( i ).x() > -23.0 && vTransit.at( i ).x() < 23.0) {
274  if ( i > 0 && fabs( vTransit.at( i ).x() - vTransit.at( i-1 ).x() ) > 6.0 ) {
275  scUI->CalendarView->addPlotObject( oTransit );
276  oTransit = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
277  needTransertLabel = true;
278  }
279  if ( needTransertLabel && vTransit.at(i).x() > scUI->CalendarView->getSetTime( i ) && vTransit.at(i).x() < scUI->CalendarView->getRiseTime( i ) ) {
280  label = i18nc( "A planet transits across the meridian", "%1 transits", ksp->name() );
281  needTransertLabel = false;
282  } else
283  label = QString();
284  if ( vTransit.at(i).x() <= scUI->CalendarView->getSetTime( i ) || vTransit.at(i).x() >= scUI->CalendarView->getRiseTime( i ) )
285  needTransertLabel = true;
286  oTransit->addPoint( vTransit.at(i), label );
287  } else {
288  scUI->CalendarView->addPlotObject( oTransit );
289  oTransit = new KPlotObject( pColor, KPlotObject::Lines, 2.0 );
290  needTransertLabel = true;
291  }
292  }
293 
294  // Add the last points
295  scUI->CalendarView->addPlotObject( oRise );
296  scUI->CalendarView->addPlotObject( oSet );
297  scUI->CalendarView->addPlotObject( oTransit );
298 }
299 
300 void SkyCalendar::slotPrint() {
301  QPainter p; // Our painter object
302  QPrinter printer; // Our printer object
303  QString str_legend; // Text legend
304  QString str_year; // Calendar's year
305  int text_height = 200; // Height of legend text zone in points
306  QSize calendar_size; // Initial calendar widget size
307  QFont calendar_font; // Initial calendar font
308  int calendar_font_size; // Initial calendar font size
309 
310  // Set printer resolution to 300 dpi
311  printer.setResolution( 300 );
312 
313  // Open print dialog
314  QPointer<QPrintDialog> dialog( KdePrint::createPrintDialog( &printer, this ) );
315  dialog->setWindowTitle( i18n( "Print sky calendar" ) );
316  if ( dialog->exec() == QDialog::Accepted ) {
317  // Change mouse cursor
318  QApplication::setOverrideCursor( Qt::WaitCursor );
319 
320  // Save calendar widget font
321  calendar_font = scUI->CalendarView->font();
322  // Save calendar widget font size
323  calendar_font_size = calendar_font.pointSize();
324  // Save calendar widget size
325  calendar_size = scUI->CalendarView->size();
326 
327  // Set text legend
328  str_year.setNum( year() );
329  str_legend = i18n( "Sky Calendar" );
330  str_legend += "\n";
331  str_legend += geo->fullName();
332  str_legend += " - ";
333  str_legend += str_year;
334 
335  // Create a rectangle for legend text zone
336  QRect text_rect( 0, 0, printer.width(), text_height );
337 
338  // Increase calendar widget font size so it looks good in 300 dpi
339  calendar_font.setPointSize( calendar_font_size * 3 );
340  scUI->CalendarView->setFont( calendar_font );
341  // Increase calendar widget size to fit the entire page
342  scUI->CalendarView->resize( printer.width(), printer.height() - text_height );
343 
344  // Create a pixmap and render calendar widget into it
345  QPixmap pixmap( scUI->CalendarView->size() );
346  scUI->CalendarView->render( &pixmap );
347 
348  // Begin painting on printer
349  p.begin( &printer );
350  // Draw legend
351  p.drawText( text_rect, Qt::AlignLeft, str_legend );
352  // Draw calendar
353  p.drawPixmap( 0, text_height, pixmap );
354  // Ending painting
355  p.end();
356 
357  // Restore calendar widget font size
358  calendar_font.setPointSize( calendar_font_size );
359  scUI->CalendarView->setFont( calendar_font );
360  // Restore calendar widget size
361  scUI->CalendarView->resize( calendar_size );
362 
363  // Restore mouse cursor
364  QApplication::restoreOverrideCursor();
365  }
366  delete dialog;
367 }
368 
369 void SkyCalendar::slotLocation() {
370  QPointer<LocationDialog> ld = new LocationDialog( this );
371  if ( ld->exec() == QDialog::Accepted ) {
372  GeoLocation *newGeo = ld->selectedCity();
373  if ( newGeo ) {
374  geo = newGeo;
375  scUI->LocationButton->setText( geo->fullName() );
376  }
377  }
378  delete ld;
379 
380  scUI->CalendarView->setHorizon();
381  slotFillCalendar();
382 }
383 
384 GeoLocation* SkyCalendar::get_geo()
385 {
386  return geo;
387 }
388 
389 #include "skycalendar.moc"
SkyObject::transitAltitude
dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo)
Definition: skyobject.cpp:245
LocationDialog
Dialog for changing the geographic location of the observer.
Definition: locationdialog.h:57
SkyCalendar::year
int year()
Definition: skycalendar.cpp:99
SkyCalendar::get_geo
GeoLocation * get_geo()
Definition: skycalendar.cpp:384
KSPlanetBase::NEPTUNE
Definition: ksplanetbase.h:82
KSPlanetBase::JUPITER
Definition: ksplanetbase.h:82
SkyCalendarUI::SkyCalendarUI
SkyCalendarUI(QWidget *p=0)
Definition: skycalendar.cpp:60
QWidget
KStarsData::Instance
static KStarsData * Instance()
Definition: kstarsdata.h:92
SkyObject::riseSetTime
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true)
Determine the time at which the point will rise or set.
Definition: skyobject.cpp:105
dms::degree
int degree() const
Definition: dms.h:79
KDialog
KStarsData::geo
GeoLocation * geo()
Definition: kstarsdata.h:164
SkyObject::transitTime
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo)
The same iteration technique described in riseSetTime() is used here.
Definition: skyobject.cpp:241
KSPlanetBase::MERCURY
Definition: ksplanetbase.h:82
geolocation.h
ksplanet.h
calendarwidget.h
skymapcomposite.h
locationdialog.h
GeoLocation
Contains all relevant information for specifying a location on Earth: City Name, State/Province name...
Definition: geolocation.h:39
SkyCalendar::slotPrint
void slotPrint()
Definition: skycalendar.cpp:300
SkyCalendar::slotLocation
void slotLocation()
Definition: skycalendar.cpp:369
KSPlanetBase::MARS
Definition: ksplanetbase.h:82
i18nc
i18nc("string from libindi, used in the config dialog","100x")
SkyCalendar::~SkyCalendar
~SkyCalendar()
Definition: skycalendar.cpp:96
KStarsDateTime
Extension of KDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day...
Definition: kstarsdatetime.h:45
KSPlanetBase::color
QColor & color()
Definition: ksplanetbase.h:190
SkyCalendar::slotFillCalendar
void slotFillCalendar()
Definition: skycalendar.cpp:101
KStarsData::skyComposite
SkyMapComposite * skyComposite()
Definition: kstarsdata.h:146
skycalendar.h
SkyCalendarUI
Definition: skycalendar.h:27
SkyMapComposite::planet
KSPlanetBase * planet(int n)
Definition: skymapcomposite.cpp:453
KSPlanetBase::SATURN
Definition: ksplanetbase.h:82
KSPlanetBase::PLUTO
Definition: ksplanetbase.h:82
NaN::ld
const long double ld
Definition: nan.h:37
GeoLocation::fullName
QString fullName() const
Definition: geolocation.cpp:56
KSPlanetBase
A subclass of TrailObject that provides additional information needed for most solar system objects...
Definition: ksplanetbase.h:63
kstarsdatetime.h
kstarsdata.h
SkyObject::name
virtual QString name(void) const
Definition: skyobject.h:124
KSPlanetBase::VENUS
Definition: ksplanetbase.h:82
QFrame
KSPlanetBase::URANUS
Definition: ksplanetbase.h:82
SkyCalendar::SkyCalendar
SkyCalendar(QWidget *parent=0)
Definition: skycalendar.cpp:66
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal