Kstars

detaildialog.cpp
1 /*
2  SPDX-FileCopyrightText: 2002 Jason Harris and Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "detaildialog.h"
8 
9 #include "config-kstars.h"
10 
11 #include "addlinkdialog.h"
12 #include "kspaths.h"
13 #include "kstars.h"
14 #include "ksnotification.h"
15 #include "kstarsdata.h"
16 #include "ksutils.h"
17 #include "observinglist.h"
18 #include "skymap.h"
19 #include "skyobjectuserdata.h"
20 #include "thumbnailpicker.h"
21 #include "skycomponents/constellationboundarylines.h"
22 #include "skycomponents/skymapcomposite.h"
23 #include "catalogobject.h"
24 #include "skyobjects/ksasteroid.h"
25 #include "skyobjects/kscomet.h"
26 #include "skyobjects/ksmoon.h"
27 #include "skyobjects/starobject.h"
28 #include "skyobjects/supernova.h"
29 #include "catalogsdb.h"
30 #include "Options.h"
31 
32 #ifdef HAVE_INDI
33 #include <basedevice.h>
34 #include "indi/indilistener.h"
35 #include "indi/indimount.h"
36 #endif
37 
38 #include <QDesktopServices>
39 #include <QDir>
40 
42  QWidget *parent)
43  : KPageDialog(parent), selectedObject(o), Data(nullptr), DataComet(nullptr),
44  Pos(nullptr), Links(nullptr), Adv(nullptr),
45  Log(nullptr), m_user_data{ KStarsData::Instance()->getUserData(o->name()) }
46 {
47 #ifdef Q_OS_OSX
48  setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
49 #endif
50  setFaceType(Tabbed);
51  setBackgroundRole(QPalette::Base);
52 
53  titlePalette = palette();
54  titlePalette.setColor(backgroundRole(), palette().color(QPalette::Active, QPalette::Highlight));
55  titlePalette.setColor(foregroundRole(), palette().color(QPalette::Active, QPalette::HighlightedText));
56 
57  //Create thumbnail image
58  Thumbnail.reset(new QPixmap(200, 200));
59 
60  setWindowTitle(i18nc("@title:window", "Object Details"));
61 
62  // JM 2016-11-22: Do we really need a close button?
63  //setStandardButtons(QDialogButtonBox::Close);
64  setStandardButtons(QDialogButtonBox::NoButton);
65 
66  createGeneralTab();
67  createPositionTab(ut, geo);
68  createLinksTab();
69  createAdvancedTab();
70  createLogTab();
71 }
72 
73 void DetailDialog::createGeneralTab()
74 {
75  Data = new DataWidget(this);
76  addPage(Data, i18n("General"));
77 
78  Data->Names->setPalette(titlePalette);
79 
80  //Connections
81  connect(Data->ObsListButton, SIGNAL(clicked()), this, SLOT(addToObservingList()));
82  connect(Data->CenterButton, SIGNAL(clicked()), this, SLOT(centerMap()));
83 #ifdef HAVE_INDI
84  connect(Data->ScopeButton, SIGNAL(clicked()), this, SLOT(centerTelescope()));
85 #else
86  Data->ScopeButton->setEnabled(false);
87 #endif
88  connect(Data->Image, SIGNAL(clicked()), this, SLOT(updateThumbnail()));
89 
90  // Stuff that should be visible only for specific types of objects
91  Data->IllumLabel->setVisible(false); // Only shown for the moon
92  Data->Illumination->setVisible(false);
93 
94  Data->BVIndex->setVisible(false); // Only shown for stars
95  Data->BVLabel->setVisible(false);
96 
97  Data->CatalogLabel->setVisible(false);
98 
99  //Show object thumbnail image
100  showThumbnail();
101 
102  //Fill in the data fields
103  //Contents depend on type of object
104  QString objecttyp;
105 
106  switch (selectedObject->type())
107  {
108  case SkyObject::STAR:
109  {
110  StarObject *s = (StarObject *)selectedObject;
111 
112  if (s->getHDIndex())
113  {
114  Data->Names->setText(
115  QString("%1, HD %2").arg(s->longname()).arg(s->getHDIndex()));
116  }
117  else
118  {
119  Data->Names->setText(s->longname());
120  }
121 
122  objecttyp = i18n("%1 star", s->sptype());
123  Data->Magnitude->setText(
124  i18nc("number in magnitudes", "%1 mag",
125  QLocale().toString(s->mag(), 'f', 2))); //show to hundredth place
126 
127  Data->BVLabel->setVisible(true);
128  Data->BVIndex->setVisible(true);
129  if (s->getBVIndex() < 30.)
130  {
131  Data->BVIndex->setText(QString::number(s->getBVIndex(), 'f', 2));
132  }
133 
134  //The thumbnail image is empty, and isn't clickable for stars
135  //Also, don't show the border around the Image QFrame.
136  Data->Image->setFrameStyle(QFrame::NoFrame);
137  disconnect(Data->Image, SIGNAL(clicked()), this, SLOT(updateThumbnail()));
138 
139  //distance
140  if (s->distance() > 2000. || s->distance() < 0.) // parallax < 0.5 mas
141  {
142  Data->Distance->setText(
143  QString(i18nc("larger than 2000 parsecs", "> 2000 pc")));
144  }
145  else if (s->distance() > 50.) //show to nearest integer
146  {
147  Data->Distance->setText(i18nc("number in parsecs", "%1 pc",
148  QLocale().toString(s->distance(), 'f', 0)));
149  }
150  else if (s->distance() > 10.0) //show to tenths place
151  {
152  Data->Distance->setText(i18nc("number in parsecs", "%1 pc",
153  QLocale().toString(s->distance(), 'f', 1)));
154  }
155  else //show to hundredths place
156  {
157  Data->Distance->setText(i18nc("number in parsecs", "%1 pc",
158  QLocale().toString(s->distance(), 'f', 2)));
159  }
160 
161  //Note multiplicity/variability in angular size label
162  Data->AngSizeLabel->setText(QString());
163  Data->AngSize->setText(QString());
164  Data->AngSizeLabel->setFont(Data->AngSize->font());
165  if (s->isMultiple() && s->isVariable())
166  {
167  Data->AngSizeLabel->setText(
168  i18nc("the star is a multiple star", "multiple") + ',');
169  Data->AngSize->setText(i18nc("the star is a variable star", "variable"));
170  }
171  else if (s->isMultiple())
172  {
173  Data->AngSizeLabel->setText(
174  i18nc("the star is a multiple star", "multiple"));
175  }
176  else if (s->isVariable())
177  {
178  Data->AngSizeLabel->setText(
179  i18nc("the star is a variable star", "variable"));
180  }
181 
182  // Add a label to indicate proper motion
183  double pmRA = s->pmRA(), pmDec = s->pmDec();
184  if (std::isfinite(pmRA) && std::isfinite(pmDec) && (pmRA != 0.0 || pmDec != 0.0))
185  {
186  // we have data : abuse the illumination label to show it!
187  Data->IllumLabel->setText(i18nc("Proper motion of a star", "Proper Motion:"));
188  Data->Illumination->setText(
189  i18nc(
190  "The first arg is proper motion in right ascension and the second in the declination. The unit stands for milliarcsecond per year",
191  "%1 %2 mas/yr",
192  QLocale().toString(pmRA, 'f', (pmRA >= 100.0 ? 1 : 2)),
193  QLocale().toString(pmDec, 'f', (pmDec >= 100.0 ? 1 : 2))
194  ));
195  Data->IllumLabel->setVisible(true);
196  Data->Illumination->setVisible(true);
197  }
198 
199  break; //end of stars case
200  }
201  case SkyObject::ASTEROID: //[fall through to planets]
202  case SkyObject::COMET: //[fall through to planets]
203  case SkyObject::MOON: //[fall through to planets]
204  case SkyObject::PLANET:
205  {
206  KSPlanetBase *ps = dynamic_cast<KSPlanetBase *>(selectedObject);
207 
208  if (!ps)
209  break;
210 
211  Data->Names->setText(ps->longname());
212 
213  //Type is "G5 star" for Sun
214  if (ps->name() == i18n("Sun"))
215  {
216  objecttyp = i18n("G5 star");
217  }
218  else if (ps->name() == i18n("Moon"))
219  {
220  objecttyp = ps->translatedName();
221  }
222  else if (ps->name() == i18nc("Asteroid name (optional)", "Pluto") ||
223  ps->name() == i18nc("Asteroid name (optional)", "Ceres") ||
224  ps->name() == i18nc("Asteroid name (optional)", "Eris"))
225  {
226  objecttyp = i18n("Dwarf planet");
227  }
228  else
229  {
230  objecttyp = ps->typeName();
231  }
232 
233  //The moon displays illumination fraction and updateMag is called to calculate moon's current magnitude
234  if (selectedObject->name() == i18n("Moon"))
235  {
236  Data->IllumLabel->setVisible(true);
237  Data->Illumination->setVisible(true);
238  Data->Illumination->setText(QString("%1 %").arg(QLocale().toString(
239  ((KSMoon *)selectedObject)->illum() * 100., 'f', 0)));
240  ((KSMoon *)selectedObject)->updateMag();
241  }
242 
243  // JM: Shouldn't we use the calculated magnitude? Disabling the following
244  /*
245  if(selectedObject->type() == SkyObject::COMET){
246  Data->Magnitude->setText(i18nc("number in magnitudes", "%1 mag",
247  QLocale().toString( ((KSComet *)selectedObject)->getTotalMagnitudeParameter(), 'f', 2))); //show to hundredth place
248 
249  }
250  else{*/
251  Data->Magnitude->setText(
252  i18nc("number in magnitudes", "%1 mag",
253  QLocale().toString(ps->mag(), 'f', 2))); //show to hundredth place
254  //}
255 
256  //Distance from Earth. The moon requires a unit conversion
257  if (ps->name() == i18n("Moon"))
258  {
259  Data->Distance->setText(
260  i18nc("distance in kilometers", "%1 km",
261  QLocale().toString(ps->rearth() * AU_KM, 'f', 2)));
262  }
263  else
264  {
265  Data->Distance->setText(i18nc("distance in Astronomical Units", "%1 AU",
266  QLocale().toString(ps->rearth(), 'f', 3)));
267  }
268 
269  //Angular size; moon and sun in arcmin, others in arcsec
270  if (ps->angSize())
271  {
272  if (ps->name() == i18n("Sun") || ps->name() == i18n("Moon"))
273  {
274  Data->AngSize->setText(i18nc(
275  "angular size in arcminutes", "%1 arcmin",
276  QLocale().toString(
277  ps->angSize(), 'f',
278  1))); // Needn't be a plural form because sun / moon will never contract to 1 arcminute
279  }
280  else
281  {
282  Data->AngSize->setText(
283  i18nc("angular size in arcseconds", "%1 arcsec",
284  QLocale().toString(ps->angSize() * 60.0, 'f', 1)));
285  }
286  }
287  else
288  {
289  Data->AngSize->setText("--");
290  }
291 
292  break; //end of planets/comets/asteroids case
293  }
294  case SkyObject::SUPERNOVA:
295  {
296  Supernova *sup = dynamic_cast<Supernova *>(selectedObject);
297 
298  objecttyp = i18n("Supernova");
299  Data->Names->setText(sup->name());
300  if (sup->mag() < 99)
301  Data->Magnitude->setText(i18nc("number in magnitudes", "%1 mag",
302  QLocale().toString(sup->mag(), 'f', 2)));
303  else
304  Data->Magnitude->setText("--");
305 
306  Data->DistanceLabel->setVisible(false);
307  Data->Distance->setVisible(false);
308 
309  Data->AngSizeLabel->setVisible(false);
310  Data->AngSize->setVisible(false);
311 
312  QLabel *discoveryDateLabel = new QLabel(i18n("Discovery Date:"), this);
313  QLabel *discoveryDate = new QLabel(sup->getDate(), this);
314  Data->dataGridLayout->addWidget(discoveryDateLabel, 1, 0);
315  Data->dataGridLayout->addWidget(discoveryDate, 1, 1);
316 
317  QLabel *typeLabel = new QLabel(i18n("Type:"), this);
318  QLabel *type = new QLabel(sup->getType(), this);
319  Data->dataGridLayout->addWidget(typeLabel, 2, 0);
320  Data->dataGridLayout->addWidget(type, 2, 1);
321 
322  QLabel *hostGalaxyLabel = new QLabel(i18n("Host Galaxy:"), this);
323  QLabel *hostGalaxy = new QLabel(
324  sup->getHostGalaxy().isEmpty() ? "--" : sup->getHostGalaxy(), this);
325  Data->dataGridLayout->addWidget(hostGalaxyLabel, 3, 0);
326  Data->dataGridLayout->addWidget(hostGalaxy, 3, 1);
327 
328  QLabel *redShiftLabel = new QLabel(i18n("Red Shift:"), this);
329  QLabel *redShift = new QLabel(
330  (sup->getRedShift() < 99) ? QString::number(sup->getRedShift(), 'f', 2) :
331  QString("--"),
332  this);
333  Data->dataGridLayout->addWidget(redShiftLabel, 4, 0);
334  Data->dataGridLayout->addWidget(redShift, 4, 1);
335 
336  break;
337  }
338  default: //deep-sky objects
339  {
340  CatalogObject *dso = dynamic_cast<CatalogObject *>(selectedObject);
341 
342  if (!dso)
343  break;
344 
345  //Show all names recorded for the object
346  QStringList nameList;
347  if (!dso->longname().isEmpty() && dso->longname() != dso->name())
348  {
349  nameList.append(dso->translatedLongName());
350  }
351 
352  nameList.append(dso->translatedName());
353 
354  if (!dso->translatedName2().isEmpty())
355  {
356  nameList.append(dso->translatedName2());
357  }
358 
359  Data->Names->setText(nameList.join(","));
360 
361  objecttyp = dso->typeName();
362 
363  if (dso->type() == SkyObject::RADIO_SOURCE)
364  {
365  Data->MagLabel->setText(
366  i18nc("integrated flux at a frequency", "Flux(%1):", 1));
367  Data->Magnitude->setText(i18nc("integrated flux value", "%1 %2",
368  QLocale().toString(dso->flux(), 'f', 1),
369  "obs")); //show to tenths place
370  }
371  else if (std::isnan(dso->mag()))
372  {
373  Data->Magnitude->setText("--");
374  }
375  else
376  {
377  Data->Magnitude->setText(
378  i18nc("number in magnitudes", "%1 mag",
379  QLocale().toString(dso->mag(), 'f', 1))); //show to tenths place
380  }
381 
382  //No distances at this point...
383  Data->Distance->setText("--");
384 
385  Data->CatalogLabel->setVisible(true);
386  Data->Catalog->setText(dso->getCatalog().name);
387 
388  //Only show decimal place for small angular sizes
389  if (dso->a() > 10.0)
390  {
391  Data->AngSize->setText(i18nc("angular size in arcminutes", "%1 arcmin",
392  QLocale().toString(dso->a(), 'f', 0)));
393  }
394  else if (dso->a())
395  {
396  Data->AngSize->setText(i18nc("angular size in arcminutes", "%1 arcmin",
397  QLocale().toString(dso->a(), 'f', 1)));
398  }
399  else
400  {
401  Data->AngSize->setText("--");
402  }
403 
404  break;
405  }
406  }
407 
408  // Add specifics data
409  switch (selectedObject->type())
410  {
411  case SkyObject::ASTEROID:
412  {
413  KSAsteroid *ast = dynamic_cast<KSAsteroid *>(selectedObject);
414  // Show same specifics data as comets
415  DataComet = new DataCometWidget(this);
416  Data->IncludeData->layout()->addWidget(DataComet);
417 
418  // Perihelion
419  DataComet->Perihelion->setText(i18nc("Distance in astronomical units",
420  "%1 AU",
421  QString::number(ast->getPerihelion())));
422  // Earth MOID
423  if (ast->getEarthMOID() == 0)
424  DataComet->EarthMOID->setText("--");
425  else
426  DataComet->EarthMOID->setText(
427  i18nc("Distance in astronomical units", "%1 AU",
428  QString::number(ast->getEarthMOID())));
429  // Orbit ID
430  DataComet->OrbitID->setText(ast->getOrbitID());
431  // Orbit Class
432  DataComet->OrbitClass->setText(ast->getOrbitClass());
433  // NEO
434  if (ast->isNEO())
435  DataComet->NEO->setText(i18n("Yes"));
436  else
437  DataComet->NEO->setText(i18n("No"));
438  // Albedo
439  if (ast->getAlbedo() == 0.0)
440  DataComet->Albedo->setText("--");
441  else
442  DataComet->Albedo->setText(QString::number(ast->getAlbedo()));
443  // Diameter
444  if (ast->getDiameter() == 0.0)
445  DataComet->Diameter->setText("--");
446  else
447  DataComet->Diameter->setText(i18nc("Diameter in kilometers", "%1 km",
448  QString::number(ast->getDiameter())));
449  // Dimensions
450  if (ast->getDimensions().isEmpty())
451  DataComet->Dimensions->setText("--");
452  else
453  DataComet->Dimensions->setText(
454  i18nc("Dimension in kilometers", "%1 km", ast->getDimensions()));
455  // Rotation period
456  if (ast->getRotationPeriod() == 0.0)
457  DataComet->Rotation->setText("--");
458  else
459  DataComet->Rotation->setText(
460  i18nc("Rotation period in hours", "%1 h",
462  // Period
463  if (ast->getPeriod() == 0.0)
464  DataComet->Period->setText("--");
465  else
466  DataComet->Period->setText(i18nc("Orbit period in years", "%1 y",
467  QString::number(ast->getPeriod())));
468  break;
469  }
470  case SkyObject::COMET:
471  {
472  KSComet *com = dynamic_cast<KSComet *>(selectedObject);
473  DataComet = new DataCometWidget(this);
474  Data->IncludeData->layout()->addWidget(DataComet);
475 
476  // Perihelion
477  DataComet->Perihelion->setText(i18nc("Distance in astronomical units",
478  "%1 AU",
479  QString::number(com->getPerihelion())));
480  // Earth MOID
481  if (com->getEarthMOID() == 0)
482  DataComet->EarthMOID->setText("--");
483  else
484  DataComet->EarthMOID->setText(
485  i18nc("Distance in astronomical units", "%1 AU",
486  QString::number(com->getEarthMOID())));
487  // Orbit ID
488  DataComet->OrbitID->setText(com->getOrbitID());
489  // Orbit Class
490  DataComet->OrbitClass->setText(com->getOrbitClass());
491  // NEO
492  if (com->isNEO())
493  DataComet->NEO->setText(i18n("Yes"));
494  else
495  DataComet->NEO->setText(i18n("No"));
496  // Albedo
497  if (com->getAlbedo() == 0.0)
498  DataComet->Albedo->setText("--");
499  else
500  DataComet->Albedo->setText(QString::number(com->getAlbedo()));
501  // Diameter
502  if (com->getDiameter() == 0.0)
503  DataComet->Diameter->setText("--");
504  else
505  DataComet->Diameter->setText(i18nc("Diameter in kilometers", "%1 km",
506  QString::number(com->getDiameter())));
507  // Dimensions
508  if (com->getDimensions().isEmpty())
509  DataComet->Dimensions->setText("--");
510  else
511  DataComet->Dimensions->setText(
512  i18nc("Dimension in kilometers", "%1 km", com->getDimensions()));
513  // Rotation period
514  if (com->getRotationPeriod() == 0.0)
515  DataComet->Rotation->setText("--");
516  else
517  DataComet->Rotation->setText(
518  i18nc("Rotation period in hours", "%1 h",
520  // Period
521  if (com->getPeriod() == 0.0)
522  DataComet->Period->setText("--");
523  else
524  DataComet->Period->setText(i18nc("Orbit period in years", "%1 y",
525  QString::number(com->getPeriod())));
526  break;
527  }
528  }
529 
530  //Common to all types:
531  QString cname = KStarsData::Instance()
532  ->skyComposite()
533  ->constellationBoundary()
534  ->constellationName(selectedObject);
535  if (selectedObject->type() != SkyObject::CONSTELLATION)
536  {
537  cname = i18nc(
538  "%1 type of sky object (planet, asteroid etc), %2 name of a constellation",
539  "%1 in %2", objecttyp, cname);
540  }
541  Data->ObjectTypeInConstellation->setText(cname);
542 }
543 
544 void DetailDialog::createPositionTab(const KStarsDateTime &ut, GeoLocation *geo)
545 {
546  Pos = new PositionWidget(this);
547  addPage(Pos, i18n("Position"));
548 
549  Pos->CoordTitle->setPalette(titlePalette);
550  Pos->RSTTitle->setPalette(titlePalette);
551  KStarsData *data = KStarsData::Instance();
552 
553  //Coordinates Section:
554  //Don't use KLocale::formatNumber() for the epoch string,
555  //because we don't want a thousands-place separator!
556  selectedObject->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false);
557  QString sEpoch = QString::number(KStarsDateTime::jdToEpoch(selectedObject->getLastPrecessJD()), 'f', 1);
558  //Replace the decimal point with localized decimal symbol
559  sEpoch.replace('.', QLocale().decimalPoint()); // Is this necessary? -- asimha Oct 2016
560 
561  /*qDebug() << Q_FUNC_INFO << (selectedObject->deprecess(data->updateNum())).ra0().toHMSString()
562  << (selectedObject->deprecess(data->updateNum())).dec0().toDMSString();*/
563  //qDebug() << Q_FUNC_INFO << selectedObject->ra().toHMSString() << selectedObject->dec().toDMSString();
564  Pos->RALabel->setText(i18n("RA (%1):", sEpoch));
565  Pos->DecLabel->setText(i18n("DE (%1):", sEpoch));
566  Pos->RA->setText(selectedObject->ra().toHMSString(false, true));
567  Pos->Dec->setText(selectedObject->dec().toDMSString(false, false, true));
568 
569  selectedObject->EquatorialToHorizontal(data->lst(), data->geo()->lat());
570 
571  Pos->Az->setText(selectedObject->az().toDMSString());
572  dms a;
573 
574  if (Options::useAltAz())
575  a = selectedObject->alt();
576  else
577  a = selectedObject->altRefracted();
578  Pos->Alt->setText(a.toDMSString());
579 
580  // Display the RA0 and Dec0 for objects that are outside the solar system
581  // 2017-09-10 JM: Exception added for asteroids and comets since we have J2000 for them.
582  // Maybe others?
583  Pos->RA0->setText(selectedObject->ra0().toHMSString(false, true));
584  Pos->Dec0->setText(selectedObject->dec0().toDMSString(false, false, true));
585 #if 0
586  if (!selectedObject->isSolarSystem() || selectedObject->type() == SkyObject::COMET || selectedObject->type() == SkyObject::ASTEROID)
587  {
588  Pos->RA0->setText(selectedObject->ra0().toHMSString());
589  Pos->Dec0->setText(selectedObject->dec0().toDMSString());
590  }
591  else
592  {
593  Pos->RA0->setText("--");
594  Pos->Dec0->setText("--");
595  }
596 #endif
597 
598  //Hour Angle can be negative, but dms HMS expressions cannot.
599  //Here's a kludgy workaround:
600  dms lst = geo->GSTtoLST(ut.gst());
601  dms ha(lst.Degrees() - selectedObject->ra().Degrees());
602  QChar sgn('+');
603  if (ha.Hours() > 12.0)
604  {
605  ha.setH(24.0 - ha.Hours());
606  sgn = '-';
607  }
608  Pos->HA->setText(QString("%1%2").arg(sgn).arg(ha.toHMSString()));
609 
610  //Airmass is approximated as the secant of the zenith distance,
611  //equivalent to 1./sin(Alt). Beware of Inf at Alt=0!
612  if (selectedObject->alt().Degrees() > 0.0)
613  Pos->Airmass->setText(QLocale().toString(selectedObject->airmass(), 'f', 2));
614  else
615  Pos->Airmass->setText("--");
616 
617  //Rise/Set/Transit Section:
618 
619  //Prepare time/position variables
620  QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
621  dms raz = selectedObject->riseSetTimeAz(ut, geo, true); //true = use rise time
622 
623  //If transit time is before rise time, use transit time for tomorrow
624  QTime tt = selectedObject->transitTime(ut, geo);
625  dms talt = selectedObject->transitAltitude(ut, geo);
626  if (tt < rt)
627  {
628  tt = selectedObject->transitTime(ut.addDays(1), geo);
629  talt = selectedObject->transitAltitude(ut.addDays(1), geo);
630  }
631 
632  // JM 2021.09.14: Set time is already taken care of
633  QTime st = selectedObject->riseSetTime(ut, geo, false); //false = use set time
634  dms saz = selectedObject->riseSetTimeAz(ut, geo, false); //false = use set time
635  // if (st < rt)
636  // {
637  // st = selectedObject->riseSetTime(ut.addDays(1), geo, false); //false = use set time
638  // saz = selectedObject->riseSetTimeAz(ut.addDays(1), geo, false); //false = use set time
639  // }
640 
641  if (rt.isValid())
642  {
643  Pos->TimeRise->setText(QString::asprintf("%02d:%02d", rt.hour(), rt.minute()));
644  Pos->TimeSet->setText(QString::asprintf("%02d:%02d", st.hour(), st.minute()));
645  Pos->AzRise->setText(raz.toDMSString());
646  Pos->AzSet->setText(saz.toDMSString());
647  }
648  else
649  {
650  if (selectedObject->alt().Degrees() > 0.0)
651  {
652  Pos->TimeRise->setText(i18n("Circumpolar"));
653  Pos->TimeSet->setText(i18n("Circumpolar"));
654  }
655  else
656  {
657  Pos->TimeRise->setText(i18n("Never rises"));
658  Pos->TimeSet->setText(i18n("Never rises"));
659  }
660 
661  Pos->AzRise->setText(i18nc("Not Applicable", "N/A"));
662  Pos->AzSet->setText(i18nc("Not Applicable", "N/A"));
663  }
664 
665  Pos->TimeTransit->setText(QString::asprintf("%02d:%02d", tt.hour(), tt.minute()));
666  Pos->AltTransit->setText(talt.toDMSString());
667 
668  // Restore the position and other time-dependent parameters
669  selectedObject->recomputeCoords(ut, geo);
670 }
671 
672 void DetailDialog::createLinksTab()
673 {
674  // don't create a link tab for an unnamed star
675  if (selectedObject->name() == QString("star"))
676  return;
677 
678  Links = new LinksWidget(this);
679  addPage(Links, i18n("Links"));
680 
681  Links->InfoTitle->setPalette(titlePalette);
682  Links->ImagesTitle->setPalette(titlePalette);
683 
684  for (const auto &link : m_user_data.websites())
685  Links->InfoTitleList->addItem(i18nc("Image/info menu item (should be translated)",
686  link.title.toLocal8Bit()));
687 
688  //Links->InfoTitleList->setCurrentRow(0);
689 
690  for (const auto &link : m_user_data.images())
691  Links->ImageTitleList->addItem(i18nc(
692  "Image/info menu item (should be translated)", link.title.toLocal8Bit()));
693 
694  // Signals/Slots
695  connect(Links->ViewButton, SIGNAL(clicked()), this, SLOT(viewLink()));
696  connect(Links->AddLinkButton, SIGNAL(clicked()), this, SLOT(addLink()));
697  connect(Links->EditLinkButton, SIGNAL(clicked()), this, SLOT(editLinkDialog()));
698  connect(Links->RemoveLinkButton, SIGNAL(clicked()), this, SLOT(removeLinkDialog()));
699 
700  // When an item is selected in info list, selected items are cleared image list.
701  connect(Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this,
703  connect(Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
704  Links->ImageTitleList, SLOT(clearSelection()));
705 
706  // vice versa
707  connect(Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this,
709  connect(Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
710  Links->InfoTitleList, SLOT(clearSelection()));
711 
712  connect(Links->InfoTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(viewLink()));
713  connect(Links->ImageTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(viewLink()));
714 
715  connect(Links->InfoTitleList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons()));
716  connect(Links->ImageTitleList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons()));
717 
718  updateLists();
719 }
720 
722 {
723  if (!selectedObject)
724  return;
725  QPointer<AddLinkDialog> adialog = new AddLinkDialog(this, selectedObject->name());
726  QString entry;
727  QFile file;
728 
729  if (adialog->exec() == QDialog::Accepted)
730  {
731  const auto &success = KStarsData::Instance()->addToUserData(
732  selectedObject->name(),
734  {
735  adialog->desc(), QUrl(adialog->url()),
736  (adialog->isImageLink()) ? SkyObjectUserdata::LinkData::Type::image :
737  SkyObjectUserdata::LinkData::Type::website });
738 
739  if (!success.first)
740  {
741  KSNotification::sorry(success.second, i18n("Could not add the link."));
742  }
743  }
744 
745  updateLists();
746  delete adialog;
747 }
748 
749 void DetailDialog::createAdvancedTab()
750 {
751  // Don't create an adv tab for an unnamed star or if advinterface file failed loading
752  // We also don't need adv dialog for solar system objects.
753  if (selectedObject->name() == QString("star") || KStarsData::Instance()->avdTree().isEmpty() ||
754  selectedObject->type() == SkyObject::PLANET || selectedObject->type() == SkyObject::COMET ||
755  selectedObject->type() == SkyObject::ASTEROID)
756  return;
757 
758  Adv = new DatabaseWidget(this);
759  addPage(Adv, i18n("Advanced"));
760 
761  connect(Adv->ADVTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(viewADVData()));
762 
763  populateADVTree();
764 }
765 
766 void DetailDialog::createLogTab()
767 {
768  //Don't create a log tab for an unnamed star
769  if (selectedObject->name() == QString("star"))
770  return;
771 
772  // Log Tab
773  Log = new LogWidget(this);
774  addPage(Log, i18n("Log"));
775 
776  Log->LogTitle->setPalette(titlePalette);
777 
778  const auto &log = m_user_data.userLog;
779 
780  if (log.isEmpty())
781  Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.",
782  selectedObject->translatedName()));
783  else
784  Log->UserLog->setText(log);
785 
786  //Automatically save the log contents when the widget loses focus
787  connect(Log->UserLog, SIGNAL(focusOut()), this, SLOT(saveLogData()));
788 }
789 
791 {
792  m_CurrentLink = it;
793 }
794 
796 {
797  QString URL;
798 
799  if (m_CurrentLink == nullptr)
800  return;
801 
802  if (m_CurrentLink->listWidget() == Links->InfoTitleList)
803  {
804  URL = m_user_data.websites()
805  .at(Links->InfoTitleList->row(m_CurrentLink))
806  .url.toString();
807  }
808  else if (m_CurrentLink->listWidget() == Links->ImageTitleList)
809  {
810  URL = m_user_data.images()
811  .at(Links->ImageTitleList->row(m_CurrentLink))
812  .url.toString();
813  }
814 
815  if (!URL.isEmpty())
817 }
818 
820 {
821  Links->InfoTitleList->clear();
822  Links->ImageTitleList->clear();
823 
824  for (const auto &element : m_user_data.websites())
825  Links->InfoTitleList->addItem(element.title);
826 
827  for (const auto &element : m_user_data.images())
828  Links->ImageTitleList->addItem(element.title);
829 
830  updateButtons();
831 }
832 
834 {
835  bool anyLink = false;
836  if (!Links->InfoTitleList->selectedItems().isEmpty() || !Links->ImageTitleList->selectedItems().isEmpty())
837  anyLink = true;
838 
839  // Buttons could be disabled if lists are initially empty, we enable and disable them here
840  // depending on the current status of the list.
841  Links->ViewButton->setEnabled(anyLink);
842  Links->EditLinkButton->setEnabled(anyLink);
843  Links->RemoveLinkButton->setEnabled(anyLink);
844 }
845 
847 {
848  SkyObjectUserdata::Type type = SkyObjectUserdata::Type::image;
849  int row = 0;
850 
851  if (m_CurrentLink == nullptr)
852  return;
853 
854  QDialog editDialog(this);
855  editDialog.setWindowTitle(i18nc("@title:window", "Edit Link"));
856 
857  QVBoxLayout *mainLayout = new QVBoxLayout;
858 
859  QFrame editFrame(&editDialog);
860 
861  mainLayout->addWidget(&editFrame);
862 
864  mainLayout->addWidget(buttonBox);
865  connect(buttonBox, SIGNAL(accepted()), &editDialog, SLOT(accept()));
866  connect(buttonBox, SIGNAL(rejected()), &editDialog, SLOT(reject()));
867 
868  editDialog.setLayout(mainLayout);
869 
870  if (m_CurrentLink->listWidget() == Links->InfoTitleList)
871  {
872  row = Links->InfoTitleList->row(m_CurrentLink);
873  type = SkyObjectUserdata::Type::website;
874  }
875  else if (m_CurrentLink->listWidget() == Links->ImageTitleList)
876  {
877  row = Links->ImageTitleList->row(m_CurrentLink);
878  type = SkyObjectUserdata::Type::image;
879  }
880  else
881  return;
882 
883  const auto &currentItem = m_user_data.links.at(type).at(row);
884 
885  QLineEdit editNameField(&editFrame);
886  editNameField.setObjectName("nameedit");
887  editNameField.home(false);
888  editNameField.setText(currentItem.title);
889  QLabel editLinkURL(i18n("URL:"), &editFrame);
890  QLineEdit editLinkField(&editFrame);
891  editLinkField.setObjectName("urledit");
892  editLinkField.home(false);
893  editLinkField.setText(currentItem.url.toString());
894  QVBoxLayout vlay(&editFrame);
895  vlay.setObjectName("vlay");
896  QHBoxLayout editLinkLayout(&editFrame);
897  editLinkLayout.setObjectName("editlinklayout");
898  editLinkLayout.addWidget(&editLinkURL);
899  editLinkLayout.addWidget(&editLinkField);
900  vlay.addWidget(&editNameField);
901  vlay.addLayout(&editLinkLayout);
902 
903  bool go(true);
904  // If user presses cancel then skip the action
905  if (editDialog.exec() != QDialog::Accepted)
906  go = false;
907 
908  // If nothing changed, skip th action
909  if (editLinkField.text() == currentItem.url.toString() &&
910  editNameField.text() == currentItem.title)
911  go = false;
912 
913  if (go)
914  {
915  const auto &success = KStarsData::Instance()->editUserData(
916  selectedObject->name(), row,
917  { editNameField.text(), QUrl{ editLinkField.text() }, type });
918 
919  if (!success.first)
920  KSNotification::sorry(success.second, i18n("Could not edit the entry."));
921 
922  // Set focus to the same item again
923  if (type == SkyObjectUserdata::Type::website)
924  Links->InfoTitleList->setCurrentRow(row);
925  else
926  Links->ImageTitleList->setCurrentRow(row);
927  }
928 
929  updateLists();
930 }
931 
933 {
934  int row = 0;
935  if (m_CurrentLink == nullptr)
936  return;
937 
938  SkyObjectUserdata::Type type;
939 
940  if (m_CurrentLink->listWidget() == Links->InfoTitleList)
941  {
942  row = Links->InfoTitleList->row(m_CurrentLink);
943  type = SkyObjectUserdata::Type::website;
944  }
945  else if (m_CurrentLink->listWidget() == Links->ImageTitleList)
946  {
947  row = Links->ImageTitleList->row(m_CurrentLink);
948  type = SkyObjectUserdata::Type::image;
949  }
950  else
951  return;
952 
954  nullptr,
955  i18n("Are you sure you want to remove the %1 link?", m_CurrentLink->text()),
956  i18n("Delete Confirmation"),
957  KStandardGuiItem::del()) != KMessageBox::Continue)
958  return;
959 
960  const auto &success =
961  KStarsData::Instance()->deleteUserData(selectedObject->name(), row, type);
962 
963  if (!success.first)
964  KSNotification::sorry(success.second, i18n("Could not delete the entry."));
965 
966  // Set focus to the 1st item in the list
967  if (type == SkyObjectUserdata::LinkData::Type::website)
968  Links->InfoTitleList->clearSelection();
969  else
970  Links->ImageTitleList->clearSelection();
971 }
972 
973 void DetailDialog::populateADVTree()
974 {
975  QTreeWidgetItem *parent = nullptr;
976  QTreeWidgetItem *temp = nullptr;
977 
978  // We populate the tree iteratively, keeping track of parents as we go
979  // This solution is more efficient than the previous recursion algorithm.
980  foreach (ADVTreeData *item, KStarsData::Instance()->avdTree())
981  {
982  switch (item->Type)
983  {
984  // Top Level
985  case 0:
986  temp = new QTreeWidgetItem(parent, QStringList(i18nc("Advanced URLs: description or category", item->Name.toLocal8Bit().data())));
987  if (parent == nullptr)
988  Adv->ADVTree->addTopLevelItem(temp);
989  parent = temp;
990 
991  break;
992 
993  // End of top level
994  case 1:
995  if (parent != nullptr)
996  parent = parent->parent();
997  break;
998 
999  // Leaf
1000  case 2:
1001  new QTreeWidgetItem(parent, QStringList(i18nc("Advanced URLs: description or category", item->Name.toLocal8Bit().data())));
1002  break;
1003  }
1004  }
1005 }
1006 
1008 {
1009  QString link;
1010  QTreeWidgetItem *current = Adv->ADVTree->currentItem();
1011 
1012  //If the item has children or is invalid, do nothing
1013  if (!current || current->childCount() > 0)
1014  return;
1015 
1016  foreach (ADVTreeData *item, KStarsData::Instance()->avdTree())
1017  {
1018  if (item->Name == current->text(0))
1019  {
1020  link = item->Link;
1021  link = parseADVData(link);
1023  return;
1024  }
1025  }
1026 }
1027 
1028 QString DetailDialog::parseADVData(const QString &inlink)
1029 {
1030  QString link = inlink;
1031  QString subLink;
1032  int index;
1033 
1034  if ((index = link.indexOf("KSOBJ")) != -1)
1035  {
1036  link.remove(index, 5);
1037  link = link.insert(index, selectedObject->name());
1038  }
1039 
1040  if ((index = link.indexOf("KSRA")) != -1)
1041  {
1042  link.remove(index, 4);
1043  subLink = QString::asprintf("%02d%02d%02d", selectedObject->ra0().hour(), selectedObject->ra0().minute(),
1044  selectedObject->ra0().second());
1045  subLink = subLink.insert(2, "%20");
1046  subLink = subLink.insert(7, "%20");
1047 
1048  link = link.insert(index, subLink);
1049  }
1050  if ((index = link.indexOf("KSDEC")) != -1)
1051  {
1052  link.remove(index, 5);
1053  if (selectedObject->dec().degree() < 0)
1054  {
1055  subLink = QString::asprintf("%03d%02d%02d", selectedObject->dec0().degree(), selectedObject->dec0().arcmin(),
1056  selectedObject->dec0().arcsec());
1057  subLink = subLink.insert(3, "%20");
1058  subLink = subLink.insert(8, "%20");
1059  }
1060  else
1061  {
1062  subLink = QString::asprintf("%02d%02d%02d", selectedObject->dec0().degree(), selectedObject->dec0().arcmin(),
1063  selectedObject->dec0().arcsec());
1064  subLink = subLink.insert(0, "%2B");
1065  subLink = subLink.insert(5, "%20");
1066  subLink = subLink.insert(10, "%20");
1067  }
1068  link = link.insert(index, subLink);
1069  }
1070 
1071  return link;
1072 }
1073 
1075 {
1076  const auto &success = KStarsData::Instance()->updateUserLog(
1077  selectedObject->name(), Log->UserLog->toPlainText());
1078 
1079  if (!success.first)
1080  KSNotification::sorry(success.second, i18n("Could not update the user log."));
1081 }
1082 
1084 {
1085  KStarsData::Instance()->observingList()->slotAddObject(selectedObject);
1086 }
1087 
1089 {
1090  SkyMap::Instance()->setClickedObject(selectedObject);
1091  SkyMap::Instance()->slotCenter();
1092 }
1093 
1095 {
1096 #ifdef HAVE_INDI
1097 
1098  if (INDIListener::Instance()->size() == 0)
1099  {
1100  KSNotification::sorry(i18n("No connected mounts found."));
1101  return;
1102  }
1103 
1104  for (auto &oneDevice : INDIListener::Instance()->getDevices())
1105  {
1106  if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE))
1107  continue;
1108 
1109  if (oneDevice->isConnected() == false)
1110  {
1111  KSNotification::error(i18n("Mount %1 is offline. Please connect and retry again.", oneDevice->getDeviceName()));
1112  return;
1113  }
1114 
1115  auto mount = dynamic_cast<ISD::Mount *>(oneDevice->getConcreteDevice(INDI::BaseDevice::TELESCOPE_INTERFACE));
1116  if (!mount)
1117  continue;
1118 
1119  // Display Sun warning on slew
1120  if (selectedObject && selectedObject->name() == i18n("Sun"))
1121  {
1122  if (KMessageBox::warningContinueCancel(nullptr, i18n("Danger! Viewing the Sun without adequate solar filters is dangerous and will result in permanent eye damage!"))
1123  == KMessageBox::Cancel)
1124  return;
1125  }
1126 
1127  mount->Slew(selectedObject);
1128  return;
1129  }
1130 
1131  KSNotification::sorry(i18n("No connected mounts found."));
1132 
1133 #endif
1134 }
1135 
1137 {
1138  //No image if object is a star
1139  if (selectedObject->type() == SkyObject::STAR ||
1140  selectedObject->type() == SkyObject::CATALOG_STAR)
1141  {
1142  Thumbnail->scaled(Data->Image->width(), Data->Image->height());
1143  Thumbnail->fill(Data->DataFrame->palette().color(QPalette::Window));
1144  Data->Image->setPixmap(*Thumbnail);
1145  return;
1146  }
1147 
1148  //Try to load the object's image from disk
1149  //If no image found, load "no image" image
1150 
1151  const auto &base = KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
1152  QDirIterator search(base, QStringList() << "thumb*", QDir::Dirs);
1153 
1154  bool found = false;
1155  while (search.hasNext())
1156  {
1157  const auto &path =
1158  QDir(search.next())
1160  "thumb-" + selectedObject->name().toLower().remove(' ').remove('/') +
1161  ".png");
1162 
1163  const QFile file{ path };
1164  if (file.exists())
1165  {
1166  Thumbnail->load(path, "PNG");
1167  found = true;
1168  }
1169  }
1170 
1171  if (!found)
1172  Thumbnail->load(":/images/noimage.png");
1173 
1174  *Thumbnail = Thumbnail->scaled(Data->Image->width(), Data->Image->height(),
1176 
1177  Data->Image->setPixmap(*Thumbnail);
1178 }
1179 
1181 {
1182  QPointer<ThumbnailPicker> tp = new ThumbnailPicker(selectedObject, *Thumbnail, this);
1183 
1184  if (tp->exec() == QDialog::Accepted)
1185  {
1186  QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).mkpath("thumbnails");
1187 
1188  QString const fname =
1189  QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
1190  .filePath("thumb-" + selectedObject->name().toLower().remove(' ').remove('/') + ".png");
1191 
1192  Data->Image->setPixmap(*(tp->image()));
1193 
1194  //If a real image was set, save it.
1195  //If the image was unset, delete the old image on disk.
1196  if (tp->imageFound())
1197  {
1198 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1199  bool rc = Data->Image->pixmap()->save(fname, "PNG");
1200  if (rc == false)
1201  {
1202  KSNotification::error(i18n("Unable to save image to %1", fname),
1203  i18n("Save Thumbnail"));
1204  }
1205  else
1206  *Thumbnail = *(Data->Image->pixmap());
1207 #else
1208  bool rc = Data->Image->pixmap(Qt::ReturnByValue).save(fname, "PNG");
1209  if (rc == false)
1210  {
1211  KSNotification::error(i18n("Unable to save image to %1", fname),
1212  i18n("Save Thumbnail"));
1213  }
1214  else
1215  *Thumbnail = (Data->Image->pixmap(Qt::ReturnByValue));
1216 #endif
1217  }
1218  else
1219  {
1220  QFile f;
1221  f.setFileName(fname);
1222  f.remove();
1223  }
1224  }
1225  delete tp;
1226 }
1227 
1228 DataWidget::DataWidget(QWidget *p) : QFrame(p)
1229 {
1230  setupUi(this);
1231  DataFrame->setBackgroundRole(QPalette::Base);
1232 }
1233 
1234 DataCometWidget::DataCometWidget(QWidget *p) : QFrame(p)
1235 {
1236  setupUi(this);
1237 }
1238 
1239 PositionWidget::PositionWidget(QWidget *p) : QFrame(p)
1240 {
1241  setupUi(this);
1242  CoordFrame->setBackgroundRole(QPalette::Base);
1243  RSTFrame->setBackgroundRole(QPalette::Base);
1244 }
1245 
1246 LinksWidget::LinksWidget(QWidget *p) : QFrame(p)
1247 {
1248  setupUi(this);
1249 }
1250 
1251 DatabaseWidget::DatabaseWidget(QWidget *p) : QFrame(p)
1252 {
1253  setupUi(this);
1254 }
1255 
1256 LogWidget::LogWidget(QWidget *p) : QFrame(p)
1257 {
1258  setupUi(this);
1259 }
void append(const T &value)
const dms & alt() const
Definition: skypoint.h:281
QString getOrbitClass() const
Definition: ksasteroid.h:118
float getRotationPeriod() const
Definition: ksasteroid.h:168
QString getDate() const
Definition: supernova.h:54
QString text() const const
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
QString getOrbitClass()
Definition: kscomet.h:130
void centerTelescope()
Slot to center this object in the telescope.
KStarsDateTime addDays(int nd) const
Modify the Date/Time by adding a number of days.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString number(int n, int base)
QString translatedLongName() const
Definition: skyobject.h:169
virtual void reject()
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
std::pair< bool, QString > editUserData(const QString &name, const unsigned int index, const SkyObjectUserdata::LinkData &data)
Replace data in the user data at index for the object with name, both in memory and on disk.
QString getType() const
Definition: supernova.h:48
int degree() const
Definition: dms.h:116
void addLink()
Popup menu function: Add a custom Image or Information URL.
bool hasNext() const const
A subclass of KSPlanetBase that implements asteroids.
Definition: ksasteroid.h:41
CachingDms * lst()
Definition: kstarsdata.h:223
A subclass of KSPlanetBase that implements comets.
Definition: kscomet.h:43
virtual QString name(void) const
Definition: skyobject.h:145
void centerMap()
Slot to center this object in the display.
bool isNEO()
Definition: kscomet.h:136
QString translatedName() const
Definition: skyobject.h:148
float mag() const
Definition: skyobject.h:206
QString getHostGalaxy() const
Definition: supernova.h:51
float getDiameter()
Definition: kscomet.h:148
bool isVariable() const
Definition: starobject.h:258
bool isValid() const const
bool openUrl(const QUrl &url)
double rearth() const
Definition: ksplanetbase.h:139
float getRedShift() const
Definition: supernova.h:57
QString next()
QListWidget * listWidget() const const
std::pair< bool, QString > deleteUserData(const QString &name, const unsigned int index, SkyObjectUserdata::Type type)
Remove data of type from the user data at index for the object with name, both in memory and on disk.
const SkyObjectUserdata::Data & getUserData(const QString &name)
Get a reference to the user data of an object with the name name.
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition: skypoint.cpp:77
double getPerihelion() const
Definition: ksasteroid.h:88
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int arcmin() const
Definition: dms.cpp:180
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
Definition: dms.cpp:370
QString translatedName2() const
Definition: skyobject.h:159
float getRotationPeriod()
Definition: kscomet.h:160
Provides necessary information about the Moon. A subclass of SkyObject that provides information need...
Definition: ksmoon.h:25
dms altRefracted() const
Definition: skypoint.cpp:1050
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void updateLists()
Rebuild the Image and Info URL lists for this object.
QString getOrbitID() const
Definition: ksasteroid.h:108
double getEarthMOID() const
Definition: ksasteroid.h:98
int getHDIndex() const
Definition: starobject.h:248
double getPerihelion()
Returns Perihelion distance.
Definition: kscomet.h:85
int type(void) const
Definition: skyobject.h:188
float a() const
void updateCoords(const KSNumbers *num, bool includePlanets=true, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, bool forceRecompute=false) override
Update position of the planet (reimplemented from SkyPoint)
double getLastPrecessJD() const
Definition: skypoint.h:294
KIOCORE_EXPORT CopyJob * link(const QList< QUrl > &src, const QUrl &destDir, JobFlags flags=DefaultFlags)
double airmass() const
Definition: skypoint.h:303
QString getOrbitID()
Definition: kscomet.h:124
void rejected()
KeepAspectRatio
QString i18n(const char *text, const TYPE &arg...)
QString longname(void) const override
If star is unnamed return "star" otherwise return the longname.
Definition: starobject.h:133
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition: dms.cpp:279
const CachingDms & dec() const
Definition: skypoint.h:269
const CachingDms * lat() const
Definition: geolocation.h:70
QString getDimensions() const
Definition: ksasteroid.h:158
void viewADVData()
Open the web browser to the selected online astronomy database, with a query to the object of this De...
char * toString(const T &value)
dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const
Definition: skyobject.cpp:190
static double jdToEpoch(long double jd, EpochType type=JULIAN)
Takes in a Julian Date and returns the corresponding epoch year in the given system.
subclass of SkyObject specialized for stars.
Definition: starobject.h:32
void setText(const QString &)
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
Definition: skyobject.cpp:93
bool isEmpty() const const
GeoLocation * geo()
Definition: kstarsdata.h:229
QString sptype(void) const
Returns entire spectral type string.
Definition: starobject.cpp:549
void setWindowTitle(const QString &)
bool mkpath(const QString &dirPath) const const
QString toString(qlonglong i) const const
double pmRA() const
Definition: starobject.h:224
QString getDimensions()
Definition: kscomet.h:154
float getPeriod() const
Definition: ksasteroid.h:178
virtual void accept()
void saveLogData()
Save the User's text in the Log Tab to the userlog.dat file.
void setClickedObject(SkyObject *o)
Set the ClickedObject pointer to the argument.
Definition: skymap.cpp:331
bool isNEO() const
Definition: ksasteroid.h:128
void addPage(KPageWidgetItem *item)
void viewLink()
Slot for viewing the selected image or info URL in the web browser.
SkyPoint recomputeCoords(const KStarsDateTime &dt, const GeoLocation *geo=nullptr) const
The equatorial coordinates for the object on date dt are computed and returned, but the object's inte...
Definition: skyobject.cpp:295
std::pair< bool, QString > updateUserLog(const QString &name, const QString &newLog)
Update the user log of the object with the name to contain newLog (find and replace).
virtual int exec()
GeoCoordinates geo(const QVariant &location)
QString join(const QString &separator) const const
std::pair< bool, QString > addToUserData(const QString &name, const SkyObjectUserdata::LinkData &data)
Adds a link data to the user data for the object with name, both in memory and on disk.
float getPeriod()
Definition: kscomet.h:166
void setupUi(QWidget *widget)
double getEarthMOID()
Definition: kscomet.h:118
DetailDialog(SkyObject *o, const KStarsDateTime &ut, GeoLocation *geo, QWidget *parent=nullptr)
Constructor.
int second() const
Definition: dms.cpp:231
int hour() const const
QString & replace(int position, int n, QChar after)
void slotCenter()
Center the display at the point ClickedPoint.
Definition: skymap.cpp:345
QString & remove(int position, int n)
SkyMapComposite * skyComposite()
Definition: kstarsdata.h:165
QString name
The catalog mame.
Definition: catalogsdb.h:45
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
double angSize() const
Definition: ksplanetbase.h:184
dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo) const
Definition: skyobject.cpp:244
static QString typeName(const int t)
Definition: skyobject.cpp:338
float getBVIndex() const
Definition: starobject.h:281
KGuiItem del()
void updateThumbnail()
Slot to update thumbnail image for the object, using the Thumbnail Picker tool.
QString toLower() const const
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
void editLinkDialog()
Open a dialog to edit a URL in either the Images or Info lists, and update the user's *url....
float flux() const
const CachingDms & ra() const
Definition: skypoint.h:263
float getAlbedo()
Definition: kscomet.h:142
QString absoluteFilePath(const QString &fileName) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
double distance() const
Definition: starobject.h:236
QString & insert(int position, QChar ch)
const CachingDms & dec0() const
Definition: skypoint.h:257
const double & Degrees() const
Definition: dms.h:141
void setObjectName(const QString &name)
float getDiameter() const
Definition: ksasteroid.h:148
void showThumbnail()
Slot to display the thumbnail image for the object.
QString filePath(const QString &fileName) const const
bool isMultiple() const
Definition: starobject.h:245
const CachingDms & ra0() const
Definition: skypoint.h:251
bool isSolarSystem() const
Definition: skyobject.h:217
int hour() const
Definition: dms.h:147
int arcsec() const
Definition: dms.cpp:193
void setCurrentLink(QListWidgetItem *it)
Set the currently-selected URL resource.
void addToObservingList()
Slot to add this object to the observing list.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
int childCount() const const
virtual QString longname(void) const
Definition: skyobject.h:164
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
Definition: skyobject.cpp:239
void addLayout(QLayout *layout, int stretch)
ReturnByValue
QString asprintf(const char *cformat,...)
int minute() const
Definition: dms.cpp:221
void setLayout(QLayout *layout)
void updateButtons()
Update View/Edit/Remove buttons.
FastTransformation
void home(bool mark)
QString text(int column) const const
float getAlbedo() const
Definition: ksasteroid.h:138
double pmDec() const
Definition: starobject.h:227
A simple container object to hold the minimum information for a Deeb Sky Object to be drawn on the sk...
Definition: catalogobject.h:40
void removeLinkDialog()
remove a URL entry from either the Images or Info lists, and update the user's *url....
QDialogButtonBox * buttonBox()
Information about an object in the sky.
Definition: skyobject.h:41
int minute() const const
QObject * parent() const const
const CatalogsDB::Catalog getCatalog() const
Get information about the catalog that this objects stems from.
Stores the tite and URL of a webpage.
Provides necessary information about objects in the solar system.
Definition: ksplanetbase.h:49
Relevant data about an observing location on Earth.
Definition: geolocation.h:27
void accepted()
const dms & az() const
Definition: skypoint.h:275
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Wed Aug 17 2022 04:14:12 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.