Kstars

detaildialoglite.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Artem Fedoskin <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "detaildialoglite.h"
8 
9 #include "constellationboundarylines.h"
10 #include "deepskyobject.h"
11 #include "kspaths.h"
12 #include "ksutils.h"
13 #include "Options.h"
14 #include "skymapcomposite.h"
15 #include "skymaplite.h"
16 #include "starobject.h"
17 #include "kstarslite/skyobjectlite.h"
18 #include "skyobjects/ksasteroid.h"
19 #include "skyobjects/kscomet.h"
20 #include "skyobjects/ksmoon.h"
21 #include "skyobjects/ksplanetbase.h"
22 #include "skyobjects/supernova.h"
23 
24 #include <QDesktopServices>
25 #include <QTemporaryFile>
26 
27 DetailDialogLite::DetailDialogLite()
28 {
29  setProperty("isLinksOn", true);
30  setProperty("isLogOn", true);
31 }
32 
33 void DetailDialogLite::initialize()
34 {
35  connect(SkyMapLite::Instance(), SIGNAL(objectLiteChanged()), this, SLOT(createGeneralTab()));
36  connect(SkyMapLite::Instance(), SIGNAL(objectLiteChanged()), this, SLOT(createPositionTab()));
37  connect(SkyMapLite::Instance(), SIGNAL(objectLiteChanged()), this, SLOT(createLogTab()));
38  connect(SkyMapLite::Instance(), SIGNAL(objectLiteChanged()), this, SLOT(createLinksTab()));
39 }
40 
41 void DetailDialogLite::createGeneralTab()
42 {
43  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
44 
45  // Stuff that should be visible only for specific types of objects
46  setProperty("illumination", ""); // Only shown for the moon
47  setProperty("BVindex", ""); // Only shown for stars
48  setupThumbnail();
49 
50  //Fill in the data fields
51  //Contents depend on type of object
52  QString objecttyp, str;
53 
54  switch (selectedObject->type())
55  {
56  case SkyObject::STAR:
57  {
58  StarObject *s = (StarObject *)selectedObject;
59 
60  if (s->getHDIndex())
61  {
62  setProperty("name", (QString("%1, HD %2").arg(s->longname()).arg(s->getHDIndex())));
63  }
64  else
65  {
66  setProperty("name", s->longname());
67  }
68 
69  objecttyp = s->sptype() + ' ' + i18n("star");
70  setProperty("magnitude", i18nc("number in magnitudes", "%1 mag",
71  QLocale().toString(s->mag(), 'f', 2))); //show to hundredth place
72 
73  if (s->getBVIndex() < 30.)
74  {
75  setProperty("BVindex", QString::number(s->getBVIndex(), 'f', 2));
76  }
77 
78  //distance
79  if (s->distance() > 2000. || s->distance() < 0.) // parallax < 0.5 mas
80  {
81  setProperty("distance", (QString(i18nc("larger than 2000 parsecs", "> 2000 pc"))));
82  }
83  else if (s->distance() > 50.) //show to nearest integer
84  {
85  setProperty("distance",
86  (i18nc("number in parsecs", "%1 pc", QLocale().toString(s->distance(), 'f', 0))));
87  }
88  else if (s->distance() > 10.0) //show to tenths place
89  {
90  setProperty("distance",
91  (i18nc("number in parsecs", "%1 pc", QLocale().toString(s->distance(), 'f', 1))));
92  }
93  else //show to hundredths place
94  {
95  setProperty("distance",
96  (i18nc("number in parsecs", "%1 pc", QLocale().toString(s->distance(), 'f', 2))));
97  }
98 
99  //Note multiplicity/variability in angular size label
100  setProperty("angSize", QString());
101  if (s->isMultiple() && s->isVariable())
102  {
103  QString multiple = QString(i18nc("the star is a multiple star", "multiple") + ',');
104  setProperty("angSize", QString(multiple + '\n' + (i18nc("the star is a variable star", "variable"))));
105  }
106  else if (s->isMultiple())
107  {
108  setProperty("angSize", i18nc("the star is a multiple star", "multiple"));
109  }
110  else if (s->isVariable())
111  {
112  setProperty("angSize", (i18nc("the star is a variable star", "variable")));
113  }
114 
115  break; //end of stars case
116  }
117  case SkyObject::ASTEROID: //[fall through to planets]
118  case SkyObject::COMET: //[fall through to planets]
119  case SkyObject::MOON: //[fall through to planets]
120  case SkyObject::PLANET:
121  {
122  KSPlanetBase *ps = (KSPlanetBase *)selectedObject;
123 
124  setProperty("name", ps->longname());
125 
126  //Type is "G5 star" for Sun
127  if (ps->name() == "Sun")
128  {
129  objecttyp = i18n("G5 star");
130  }
131  else if (ps->name() == "Moon")
132  {
133  objecttyp = ps->translatedName();
134  }
135  else if (ps->name() == i18n("Pluto") || ps->name() == "Ceres" ||
136  ps->name() == "Eris") // TODO: Check if Ceres / Eris have translations and i18n() them
137  {
138  objecttyp = i18n("Dwarf planet");
139  }
140  else
141  {
142  objecttyp = ps->typeName();
143  }
144 
145  //The moon displays illumination fraction and updateMag is called to calculate moon's current magnitude
146  if (selectedObject->name() == "Moon")
147  {
148  setProperty(
149  "illumination",
150  (QString("%1 %").arg(QLocale().toString(((KSMoon *)selectedObject)->illum() * 100., 'f', 0))));
151  ((KSMoon *)selectedObject)->updateMag();
152  }
153 
154  // JM: Shouldn't we use the calculated magnitude? Disabling the following
155  /*
156  if(selectedObject->type() == SkyObject::COMET){
157  Data->Magnitude->setText(i18nc("number in magnitudes", "%1 mag",
158  QLocale().toString( ((KSComet *)selectedObject)->getTotalMagnitudeParameter(), 'f', 2))); //show to hundredth place
159 
160  }
161  else{*/
162  setProperty("magnitude", (i18nc("number in magnitudes", "%1 mag",
163  QLocale().toString(ps->mag(), 'f', 2)))); //show to hundredth place
164  //}
165 
166  //Distance from Earth. The moon requires a unit conversion
167  if (ps->name() == "Moon")
168  {
169  setProperty("distance", (i18nc("distance in kilometers", "%1 km",
170  QLocale().toString(ps->rearth() * AU_KM, 'f', 2))));
171  }
172  else
173  {
174  setProperty("distance", (i18nc("distance in Astronomical Units", "%1 AU",
175  QLocale().toString(ps->rearth(), 'f', 3))));
176  }
177 
178  //Angular size; moon and sun in arcmin, others in arcsec
179  if (ps->angSize())
180  {
181  if (ps->name() == "Sun" || ps->name() == "Moon")
182  {
183  setProperty(
184  "angSize",
185  (i18nc(
186  "angular size in arcminutes", "%1 arcmin",
187  QLocale().toString(
188  ps->angSize(), 'f',
189  1)))); // Needn't be a plural form because sun / moon will never contract to 1 arcminute
190  }
191  else
192  {
193  setProperty("angSize", i18nc("angular size in arcseconds", "%1 arcsec",
194  QLocale().toString(ps->angSize() * 60.0, 'f', 1)));
195  }
196  }
197  else
198  {
199  setProperty("angSize", "--");
200  }
201 
202  break; //end of planets/comets/asteroids case
203  }
204  case SkyObject::SUPERNOVA:
205  {
206  Supernova *sup = (Supernova *)selectedObject;
207 
208  objecttyp = i18n("Supernova");
209  setProperty("name", sup->name());
210  setProperty("magnitude", (i18nc("number in magnitudes", "%1 mag", QLocale().toString(sup->mag(), 'f', 2))));
211  setProperty("distance", "---");
212  break;
213  }
214  default: //deep-sky objects
215  {
216  DeepSkyObject *dso = (DeepSkyObject *)selectedObject;
217 
218  //Show all names recorded for the object
219  QStringList nameList;
220  if (!dso->longname().isEmpty() && dso->longname() != dso->name())
221  {
222  nameList.append(dso->translatedLongName());
223  nameList.append(dso->translatedName());
224  }
225  else
226  {
227  nameList.append(dso->translatedName());
228  }
229 
230  if (!dso->translatedName2().isEmpty())
231  {
232  nameList.append(dso->translatedName2());
233  }
234 
235  if (dso->ugc() != 0)
236  {
237  nameList.append(QString("UGC %1").arg(dso->ugc()));
238  }
239 
240  if (dso->pgc() != 0)
241  {
242  nameList.append(QString("PGC %1").arg(dso->pgc()));
243  }
244 
245  setProperty("name", nameList.join(","));
246 
247  objecttyp = dso->typeName();
248 
249  if (dso->type() == SkyObject::RADIO_SOURCE)
250  {
251  //ta->MagLabel->setText(i18nc("integrated flux at a frequency", "Flux(%1):", dso->customCatalog()->fluxFrequency()));
252  //Data->Magnitude->setText(i18nc("integrated flux value", "%1 %2",
253  // QLocale().toString(dso->flux(), 'f', 1), dso->customCatalog()->fluxUnit())); //show to tenths place
254  }
255  else if (dso->mag() > 90.0)
256  {
257  setProperty("magnitude", "--");
258  }
259  else
260  {
261  setProperty("magnitude", i18nc("number in magnitudes", "%1 mag",
262  QLocale().toString(dso->mag(), 'f', 1))); //show to tenths place
263  }
264 
265  //No distances at this point...
266  setProperty("distance", "--");
267 
268  //Only show decimal place for small angular sizes
269  if (dso->a() > 10.0)
270  {
271  setProperty("angSize",
272  i18nc("angular size in arcminutes", "%1 arcmin", QLocale().toString(dso->a(), 'f', 0)));
273  }
274  else if (dso->a())
275  {
276  setProperty("angSize",
277  i18nc("angular size in arcminutes", "%1 arcmin", QLocale().toString(dso->a(), 'f', 1)));
278  }
279  else
280  {
281  setProperty("angSize", "--");
282  }
283 
284  break;
285  }
286  }
287 
288  //Reset advanced properties
289  setProperty("perihilion", "");
290  setProperty("orbitID", "");
291  setProperty("NEO", "");
292  setProperty("diameter", "");
293  setProperty("rotation", "");
294  setProperty("earthMOID", "");
295  setProperty("orbitClass", "");
296  setProperty("albedo", "");
297  setProperty("dimensions", "");
298  setProperty("period", "");
299 
300  // Add specifics data
301  switch (selectedObject->type())
302  {
303  case SkyObject::ASTEROID:
304  {
305  KSAsteroid *ast = (KSAsteroid *)selectedObject;
306 
307  // Perihelion
308  str.setNum(ast->getPerihelion());
309  setProperty("perihelion", QString(str + " AU"));
310  // Earth MOID
311  if (ast->getEarthMOID() == 0)
312  str = "";
313  else
314  str.setNum(ast->getEarthMOID()).append(" AU");
315  setProperty("earthMOID", str);
316  // Orbit ID
317  setProperty("orbitID", ast->getOrbitID());
318  // Orbit Class
319  setProperty("orbitClass", ast->getOrbitClass());
320  // NEO
321  if (ast->isNEO())
322  setProperty("NEO", "Yes");
323  else
324  setProperty("NEO", "No");
325  // Albedo
326  if (ast->getAlbedo() == 0.0)
327  str = "";
328  else
329  str.setNum(ast->getAlbedo());
330  setProperty("albedo", str);
331  // Diameter
332  if (ast->getDiameter() == 0.0)
333  str = "";
334  else
335  str.setNum(ast->getDiameter()).append(" km");
336  setProperty("diameter", str);
337  // Dimensions
338  if (ast->getDimensions().isEmpty())
339  setProperty("dimensions", "");
340  else
341  setProperty("dimensions", QString(ast->getDimensions() + " km"));
342  // Rotation period
343  if (ast->getRotationPeriod() == 0.0)
344  str = "";
345  else
346  str.setNum(ast->getRotationPeriod()).append(" h");
347  setProperty("rotation", str);
348  // Period
349  if (ast->getPeriod() == 0.0)
350  str = "";
351  else
352  str.setNum(ast->getPeriod()).append(" y");
353  setProperty("period", str);
354 
355  break;
356  }
357  case SkyObject::COMET:
358  {
359  KSComet *com = (KSComet *)selectedObject;
360 
361  // Perihelion
362  str.setNum(com->getPerihelion());
363  setProperty("perihelion", QString(str + " AU"));
364  // Earth MOID
365  if (com->getEarthMOID() == 0)
366  str = "";
367  else
368  str.setNum(com->getEarthMOID()).append(" AU");
369  setProperty("earthMOID", str);
370  // Orbit ID
371  setProperty("orbitID", com->getOrbitID());
372  // Orbit Class
373  setProperty("orbitClass", com->getOrbitClass());
374  // NEO
375  if (com->isNEO())
376  setProperty("NEO", "Yes");
377  else
378  setProperty("NEO", "No");
379  // Albedo
380  if (com->getAlbedo() == 0.0)
381  str = "";
382  else
383  str.setNum(com->getAlbedo());
384  setProperty("albedo", str);
385  // Diameter
386  if (com->getDiameter() == 0.0)
387  str = "";
388  else
389  str.setNum(com->getDiameter()).append(" km");
390  setProperty("diameter", str);
391  // Dimensions
392  if (com->getDimensions().isEmpty())
393  setProperty("dimensions", "");
394  else
395  setProperty("dimensions", QString(com->getDimensions() + " km"));
396  // Rotation period
397  if (com->getRotationPeriod() == 0.0)
398  str = "";
399  else
400  str.setNum(com->getRotationPeriod()).append(" h");
401  setProperty("rotation", str);
402  // Period
403  if (com->getPeriod() == 0.0)
404  str = "";
405  else
406  str.setNum(com->getPeriod()).append(" y");
407  setProperty("period", str);
408 
409  break;
410  }
411  }
412 
413  //Common to all types:
414  QString cname = KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName(selectedObject);
415  if (selectedObject->type() != SkyObject::CONSTELLATION)
416  {
417  cname = i18nc("%1 type of sky object (planet, asteroid etc), %2 name of a constellation", "%1 in %2", objecttyp,
418  cname);
419  }
420  setProperty("typeInConstellation", cname);
421 }
422 
423 void DetailDialogLite::createPositionTab()
424 {
425  KStarsData *data = KStarsData::Instance();
426  KStarsDateTime ut = data->ut();
427  GeoLocation *geo = data->geo();
428 
429  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
430 
431  //Coordinates Section:
432  //Don't use KLocale::formatNumber() for the epoch string,
433  //because we don't want a thousands-place separator!
434  QString sEpoch = QString::number(ut.epoch(), 'f', 1);
435  //Replace the decimal point with localized decimal symbol
436  sEpoch.replace('.', QLocale().decimalPoint());
437 
438  qDebug() << (selectedObject->deprecess(data->updateNum(), 2451545.0l)).ra0().toHMSString()
439  << (selectedObject->deprecess(data->updateNum(), 2451545.0l)).dec0().toDMSString() << endl;
440  //qDebug() << selectedObject->ra().toHMSString() << selectedObject->dec().toDMSString() << endl;
441  setProperty("RALabel", i18n("RA (%1):", sEpoch));
442  setProperty("decLabel", i18n("Dec (%1):", sEpoch));
443  setProperty("RA", selectedObject->ra().toHMSString());
444  setProperty("dec", selectedObject->dec().toDMSString());
445 
446  selectedObject->EquatorialToHorizontal(data->lst(), data->geo()->lat());
447 
448  setProperty("az", selectedObject->az().toDMSString());
449  dms a;
450 
451  if (Options::useAltAz())
452  a = selectedObject->alt();
453  else
454  a = selectedObject->altRefracted();
455  setProperty("alt", a.toDMSString());
456 
457  // Display the RA0 and Dec0 for objects that are outside the solar system
458  if (!selectedObject->isSolarSystem())
459  {
460  setProperty("RA0", selectedObject->ra0().toHMSString());
461  setProperty("dec0", selectedObject->dec0().toDMSString());
462  }
463  else
464  {
465  setProperty("RA0", "--");
466  setProperty("dec0", "--");
467  }
468 
469  //Hour Angle can be negative, but dms HMS expressions cannot.
470  //Here's a kludgy workaround:
471  dms lst = geo->GSTtoLST(ut.gst());
472  dms ha(lst.Degrees() - selectedObject->ra().Degrees());
473  QChar sgn('+');
474  if (ha.Hours() > 12.0)
475  {
476  ha.setH(24.0 - ha.Hours());
477  sgn = '-';
478  }
479  setProperty("HA", QString("%1%2").arg(sgn).arg(ha.toHMSString()));
480 
481  //Airmass is approximated as the secant of the zenith distance,
482  //equivalent to 1./sin(Alt). Beware of Inf at Alt=0!
483  if (selectedObject->alt().Degrees() > 0.0)
484  setProperty("airmass", QLocale().toString(selectedObject->airmass(), 'f', 2));
485  else
486  setProperty("airmass", "--");
487 
488  //Rise/Set/Transit Section:
489 
490  //Prepare time/position variables
491  QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
492  dms raz = selectedObject->riseSetTimeAz(ut, geo, true); //true = use rise time
493 
494  //If transit time is before rise time, use transit time for tomorrow
495  QTime tt = selectedObject->transitTime(ut, geo);
496  dms talt = selectedObject->transitAltitude(ut, geo);
497  if (tt < rt)
498  {
499  tt = selectedObject->transitTime(ut.addDays(1), geo);
500  talt = selectedObject->transitAltitude(ut.addDays(1), geo);
501  }
502 
503  //If set time is before rise time, use set time for tomorrow
504  QTime st = selectedObject->riseSetTime(ut, geo, false); //false = use set time
505  dms saz = selectedObject->riseSetTimeAz(ut, geo, false); //false = use set time
506  if (st < rt)
507  {
508  st = selectedObject->riseSetTime(ut.addDays(1), geo, false); //false = use set time
509  saz = selectedObject->riseSetTimeAz(ut.addDays(1), geo, false); //false = use set time
510  }
511 
512  if (rt.isValid())
513  {
514  setProperty("timeRise", QString().sprintf("%02d:%02d", rt.hour(), rt.minute()));
515  setProperty("timeSet", QString().sprintf("%02d:%02d", st.hour(), st.minute()));
516  setProperty("azRise", raz.toDMSString());
517  setProperty("azSet", saz.toDMSString());
518  }
519  else
520  {
521  if (selectedObject->alt().Degrees() > 0.0)
522  {
523  setProperty("timeRise", i18n("Circumpolar"));
524  setProperty("timeSet", i18n("Circumpolar"));
525  }
526  else
527  {
528  setProperty("timeRise", i18n("Never rises"));
529  setProperty("timeSet", i18n("Never rises"));
530  }
531 
532  setProperty("azRise", i18nc("Not Applicable", "N/A"));
533  setProperty("azSet", i18nc("Not Applicable", "N/A"));
534  }
535 
536  setProperty("timeTransit", QString().sprintf("%02d:%02d", tt.hour(), tt.minute()));
537  setProperty("altTransit", talt.toDMSString());
538 
539  // Restore the position and other time-dependent parameters
540  selectedObject->recomputeCoords(ut, geo);
541 }
542 
543 void DetailDialogLite::createLogTab()
544 {
545  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
546  //Don't create a log tab for an unnamed star
547  if (selectedObject->name() == QString("star"))
548  {
549  setProperty("isLogOn", false);
550  return;
551  }
552  setProperty("isLogOn", true);
553 
554  if (selectedObject->userLog().isEmpty())
555  {
556  setProperty("userLog",
557  i18n("Record here observation logs and/or data on %1.", selectedObject->translatedName()));
558  }
559  else
560  {
561  setProperty("userLog", selectedObject->userLog());
562  }
563 
564  /*//Automatically save the log contents when the widget loses focus
565  connect( Log->UserLog, SIGNAL(focusOut()), this, SLOT(saveLogData()) );*/
566 }
567 
568 void DetailDialogLite::createLinksTab()
569 {
570  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
571 
572  //No links for unnamed stars
573  if (selectedObject->name() == QString("star"))
574  {
575  setProperty("isLinksOn", false);
576  return;
577  }
578 
579  setProperty("isLinksOn", true);
580 
581  QStringList newInfoList;
582  foreach (const QString &s, selectedObject->InfoTitle())
583  newInfoList.append(i18nc("Image/info menu item (should be translated)", s.toLocal8Bit()));
584  setProperty("infoTitleList", newInfoList);
585 
586  QStringList newImageList;
587  foreach (const QString &s, selectedObject->ImageTitle())
588  newImageList.append(i18nc("Image/info menu item (should be translated)", s.toLocal8Bit()));
589 
590  setProperty("imageTitleList", newImageList);
591 }
592 
593 void DetailDialogLite::updateLocalDatabase(int type, const QString &search_line, const QString &replace_line)
594 {
595  QString TempFileName, file_line;
596  QFile URLFile;
597  QTemporaryFile TempFile;
598  QTextStream *temp_stream = nullptr;
599  QTextStream *out_stream = nullptr;
600  bool replace = !replace_line.isEmpty();
601 
602  if (search_line.isEmpty())
603  return;
604 
605  TempFile.setAutoRemove(false);
606  TempFile.open();
607  TempFileName = TempFile.fileName();
608 
609  switch (type)
610  {
611  // Info Links
612  case 0:
613  // Get name for our local info_url file
614  URLFile.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("info_url.dat"));
615  break;
616 
617  // Image Links
618  case 1:
619  // Get name for our local info_url file
620  URLFile.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("image_url.dat"));
621  break;
622  }
623 
624  if (!URLFile.open(QIODevice::ReadWrite))
625  {
626  qDebug() << "DetailDialog: Failed to open " << URLFile.fileName();
627  qDebug() << "KStars cannot save to user database";
628  return;
629  }
630 
631  // Copy URL file to temp file
632  TempFile.write(URLFile.readAll());
633  //Return pointers to initial positions
634  TempFile.seek(0);
635  //Clear URLFile
636  URLFile.resize(0);
637 
638  // Get streams;
639  temp_stream = new QTextStream(&TempFile);
640  out_stream = new QTextStream(&URLFile);
641 
642  while (!temp_stream->atEnd())
643  {
644  file_line = temp_stream->readLine();
645  // If we find a match, either replace, or remove (by skipping).
646  if (file_line == search_line)
647  {
648  if (replace)
649  (*out_stream) << replace_line << endl;
650  else
651  continue;
652  }
653  else
654  (*out_stream) << file_line << endl;
655  }
656 
657  URLFile.close();
658  delete temp_stream;
659  delete out_stream;
660 }
661 
662 void DetailDialogLite::addLink(const QString &url, const QString &desc, bool isImageLink)
663 {
664  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
665 
666  if (url.isEmpty() || desc.isEmpty())
667  return; //Do nothing if empty url or desc were provided
668 
669  QString entry;
670  QFile file;
671 
672  if (isImageLink)
673  {
674  //Add link to object's ImageList, and descriptive text to its ImageTitle list
675  selectedObject->ImageList().append(url);
676  selectedObject->ImageTitle().append(desc);
677 
678  //Also, update the user's custom image links database
679  //check for user's image-links database. If it doesn't exist, create it.
680  //determine filename in local user KDE directory tree.
681  file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("image_url.dat"));
682 
684  {
685  QString message =
686  i18n("Custom image-links file could not be opened.\nLink cannot be recorded for future sessions.");
687  qDebug() << message;
688  return;
689  }
690  else
691  {
692  entry = selectedObject->name() + ':' + desc + ':' + url;
693  QTextStream stream(&file);
694  stream << entry << endl;
695  file.close();
696  setProperty("imageTitleList", selectedObject->ImageTitle());
697  }
698  }
699  else
700  {
701  selectedObject->InfoList().append(url);
702  selectedObject->InfoTitle().append(desc);
703 
704  //check for user's image-links database. If it doesn't exist, create it.
705  //determine filename in local user KDE directory tree.
706  file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("info_url.dat"));
707 
709  {
710  QString message = i18n(
711  "Custom information-links file could not be opened.\nLink cannot be recorded for future sessions.");
712  qDebug() << message;
713  return;
714  }
715  else
716  {
717  entry = selectedObject->name() + ':' + desc + ':' + url;
718  QTextStream stream(&file);
719  stream << entry << endl;
720  file.close();
721  setProperty("infoTitleList", selectedObject->InfoTitle());
722  }
723  }
724 }
725 
726 void DetailDialogLite::removeLink(int itemIndex, bool isImage)
727 {
728  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
729 
730  QString currentItemURL, currentItemTitle, LineEntry, TempFileName, FileLine;
731  QFile URLFile;
732  QTemporaryFile TempFile;
733  TempFile.setAutoRemove(false);
734  TempFile.open();
735  TempFileName = TempFile.fileName();
736 
737  //Check if it is a valid index
738  if (itemIndex < 0)
739  {
740  return;
741  }
742  else if (isImage && itemIndex >= selectedObject->ImageTitle().length())
743  {
744  return;
745  }
746  else if (!isImage && itemIndex >= selectedObject->InfoTitle().length())
747  {
748  return;
749  }
750  //if (title.isEmpty() || url.isEmpty()) return;
751 
752  if (!isImage) //Information
753  {
754  currentItemTitle = selectedObject->InfoTitle()[itemIndex];
755  currentItemURL = selectedObject->InfoList()[itemIndex];
756  LineEntry = selectedObject->name();
757  LineEntry += ':';
758  LineEntry += currentItemTitle;
759  LineEntry += ':';
760  LineEntry += currentItemURL;
761  }
762  else //Image
763  {
764  currentItemTitle = selectedObject->ImageTitle()[itemIndex];
765  currentItemURL = selectedObject->ImageList()[itemIndex];
766  LineEntry = selectedObject->name();
767  LineEntry += ':';
768  LineEntry += currentItemTitle;
769  LineEntry += ':';
770  LineEntry += currentItemURL;
771  }
772 
773  /*if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 link?", currentItemTitle), i18n("Delete Confirmation"),KStandardGuiItem::del())!=KMessageBox::Continue)
774  return;*/
775 
776  if (isImage)
777  {
778  selectedObject->ImageTitle().removeAt(itemIndex);
779  selectedObject->ImageList().removeAt(itemIndex);
780  }
781  else
782  {
783  selectedObject->InfoTitle().removeAt(itemIndex);
784  selectedObject->InfoList().removeAt(itemIndex);
785  }
786 
787  // Remove link from file
788  updateLocalDatabase(isImage ? 1 : 0, LineEntry);
789 
790  setProperty("infoTitleList", selectedObject->InfoTitle());
791  setProperty("imageTitleList", selectedObject->ImageTitle());
792 }
793 
794 void DetailDialogLite::editLink(int itemIndex, bool isImage, const QString &desc, const QString &url)
795 {
796  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
797 
798  if (url.isEmpty() || desc.isEmpty())
799  return; //Do nothing if empty url or desc were provided
800 
801  QString search_line, replace_line, currentItemTitle, currentItemURL;
802 
803  //Check if it is a valid index
804  if (itemIndex < 0)
805  {
806  return;
807  }
808  else if (isImage && itemIndex >= selectedObject->ImageTitle().length())
809  {
810  return;
811  }
812  else if (!isImage && itemIndex >= selectedObject->InfoTitle().length())
813  {
814  return;
815  }
816 
817  if (!isImage) //Information
818  {
819  currentItemTitle = selectedObject->InfoTitle()[itemIndex];
820  currentItemURL = selectedObject->InfoList()[itemIndex];
821  search_line = selectedObject->name();
822  search_line += ':';
823  search_line += currentItemTitle;
824  search_line += ':';
825  search_line += currentItemURL;
826  }
827  else //Image
828  {
829  currentItemTitle = selectedObject->ImageTitle()[itemIndex];
830  currentItemURL = selectedObject->ImageList()[itemIndex];
831  search_line = selectedObject->name();
832  search_line += ':';
833  search_line += currentItemTitle;
834  search_line += ':';
835  search_line += currentItemURL;
836  }
837 
838  bool go(true);
839 
840  // If nothing changed, skip th action
841  if (url == currentItemURL && desc == currentItemTitle)
842  go = false;
843 
844  if (go)
845  {
846  replace_line = selectedObject->name() + ':' + desc + ':' + url;
847 
848  // Info Link
849  if (!isImage)
850  {
851  selectedObject->InfoTitle().replace(itemIndex, desc);
852  selectedObject->InfoList().replace(itemIndex, url);
853 
854  // Image Links
855  }
856  else
857  {
858  selectedObject->ImageTitle().replace(itemIndex, desc);
859  selectedObject->ImageList().replace(itemIndex, url);
860  }
861 
862  // Update local files
863  updateLocalDatabase(isImage ? 1 : 0, search_line, replace_line);
864 
865  setProperty("infoTitleList", selectedObject->InfoTitle());
866  setProperty("imageTitleList", selectedObject->ImageTitle());
867  }
868 }
869 
870 QString DetailDialogLite::getInfoURL(int index)
871 {
872  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
873  QStringList urls = selectedObject->InfoList();
874  if (index >= 0 && index < urls.size())
875  {
876  return urls[index];
877  }
878  else
879  {
880  return "";
881  }
882 }
883 
884 QString DetailDialogLite::getImageURL(int index)
885 {
886  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
887  QStringList urls = selectedObject->ImageList();
888  if (index >= 0 && index < urls.size())
889  {
890  return urls[index];
891  }
892  else
893  {
894  return "";
895  }
896 }
897 
898 void DetailDialogLite::setupThumbnail()
899 {
900  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
901  //No image if object is a star
902  if (selectedObject->type() == SkyObject::STAR || selectedObject->type() == SkyObject::CATALOG_STAR)
903  {
904  /*Thumbnail->scaled( Data->Image->width(), Data->Image->height() );
905  Thumbnail->fill( Data->DataFrame->palette().color( QPalette::Window ) );
906  Data->Image->setPixmap( *Thumbnail );*/
907  setProperty("thumbnail", "");
908  return;
909  }
910 
911  //Try to load the object's image from disk
912  //If no image found, load "no image" image
913  QFile file;
914  QString fname = "thumb-" + selectedObject->name().toLower().remove(' ') + ".png";
915  if (KSUtils::openDataFile(file, fname))
916  {
917  file.close();
918  setProperty("thumbnail", file.fileName());
919  }
920  else
921  {
922  setProperty("thumbnail", "");
923  }
924 }
925 
926 /*void DetailDialogLite::viewResource(int itemIndex, bool isImage) {
927  QString url;
928  if(isImage) {
929  url = getImageURL(itemIndex);
930  } else {
931  url = getInfoURL(itemIndex);
932  }
933  QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
934 }*/
935 
936 void DetailDialogLite::saveLogData(const QString &userLog)
937 {
938  SkyObject *selectedObject = SkyMapLite::Instance()->getClickedObjectLite()->getObject();
939 
940  selectedObject->saveUserLog(userLog);
941 }
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
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
QString getOrbitClass()
Definition: kscomet.h:130
SkyObjectLite * getClickedObjectLite()
getter for clickedObjectLite
Definition: skymaplite.h:401
KStarsDateTime addDays(int nd) const
Modify the Date/Time by adding a number of days.
QTextStream & endl(QTextStream &stream)
QString number(int n, int base)
virtual bool resize(qint64 sz) override
virtual bool open(QIODevice::OpenMode mode) override
void setAutoRemove(bool b)
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
QCA_EXPORT void setProperty(const QString &name, const QVariant &value)
bool isNEO()
Definition: kscomet.h:136
QString translatedName() const
Definition: skyobject.h:148
float mag() const
Definition: skyobject.h:206
float getDiameter()
Definition: kscomet.h:148
bool isVariable() const
Definition: starobject.h:258
bool isValid() const const
double rearth() const
Definition: ksplanetbase.h:139
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
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
Definition: dms.cpp:370
float getRotationPeriod()
Definition: kscomet.h:160
virtual QString fileName() const const override
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
virtual QString fileName() const const override
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
double airmass() const
Definition: skypoint.h:303
int size() const const
QString getOrbitID()
Definition: kscomet.h:124
QString i18n(const char *text, const TYPE &arg...)
double epoch() const
This is (approximately) the year expressed as a floating-point value.
QString & setNum(short n, int base)
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
bool atEnd() const const
char * toString(const T &value)
dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const
Definition: skyobject.cpp:190
subclass of SkyObject specialized for stars.
Definition: starobject.h:32
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 readLine(qint64 maxlen)
QString sptype(void) const
Returns entire spectral type string.
Definition: starobject.cpp:549
QString getDimensions()
Definition: kscomet.h:154
float getPeriod() const
Definition: ksasteroid.h:178
const QList< QKeySequence > & replace()
bool isNEO() const
Definition: ksasteroid.h:128
void setFileName(const QString &name)
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
virtual bool seek(qint64 pos) override
GeoCoordinates geo(const QVariant &location)
QString join(const QString &separator) const const
virtual void close() override
float getPeriod()
Definition: kscomet.h:166
double getEarthMOID()
Definition: kscomet.h:118
int hour() const const
QString & replace(int position, int n, QChar after)
QString & remove(int position, int n)
SkyMapComposite * skyComposite()
Definition: kstarsdata.h:165
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
const KStarsDateTime & ut() const
Definition: kstarsdata.h:156
static QString typeName(const int t)
Definition: skyobject.cpp:338
float getBVIndex() const
Definition: starobject.h:281
SkyPoint deprecess(const KSNumbers *num, long double epoch=J2000)
Obtain a Skypoint with RA0 and Dec0 set from the RA, Dec of this skypoint.
Definition: skypoint.cpp:257
QString toLower() const const
const CachingDms & ra() const
Definition: skypoint.h:263
float getAlbedo()
Definition: kscomet.h:142
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
double distance() const
Definition: starobject.h:236
const CachingDms & dec0() const
Definition: skypoint.h:257
const double & Degrees() const
Definition: dms.h:141
float getDiameter() const
Definition: ksasteroid.h:148
bool isMultiple() const
Definition: starobject.h:245
const CachingDms & ra0() const
Definition: skypoint.h:251
bool isSolarSystem() const
Definition: skyobject.h:217
QString i18nc(const char *context, const char *text, const TYPE &arg...)
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
QByteArray readAll()
SkyObject * getObject() const
Definition: skyobjectlite.h:35
QByteArray toLocal8Bit() const const
float getAlbedo() const
Definition: ksasteroid.h:138
Information about an object in the sky.
Definition: skyobject.h:41
int minute() const const
QString message
QString & append(QChar ch)
qint64 write(const char *data, qint64 maxSize)
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
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 Fri Aug 19 2022 03:57:50 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.