Kstars

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

KDE's Doxygen guidelines are available online.