File indexing completed on 2025-04-27 06:41:02
0001 /* 0002 SPDX-FileCopyrightText: 2002 Jason Harris and Jasem Mutlaq <kstars@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "detaildialog.h" 0008 0009 #include "config-kstars.h" 0010 0011 #include "addlinkdialog.h" 0012 #include "kspaths.h" 0013 #include "ksnotification.h" 0014 #include "kstarsdata.h" 0015 #include "observinglist.h" 0016 #include "skymap.h" 0017 #include "skyobjectuserdata.h" 0018 #include "thumbnailpicker.h" 0019 #include "skycomponents/constellationboundarylines.h" 0020 #include "skycomponents/skymapcomposite.h" 0021 #include "catalogobject.h" 0022 #include "skyobjects/ksasteroid.h" 0023 #include "skyobjects/kscomet.h" 0024 #include "skyobjects/ksmoon.h" 0025 #include "skyobjects/starobject.h" 0026 #include "skyobjects/supernova.h" 0027 #include "catalogsdb.h" 0028 #include "Options.h" 0029 0030 #ifdef HAVE_INDI 0031 #include "indi/indilistener.h" 0032 #include "indi/indimount.h" 0033 #endif 0034 0035 #include <QDesktopServices> 0036 #include <QDir> 0037 #include <QDirIterator> 0038 0039 DetailDialog::DetailDialog(SkyObject *o, const KStarsDateTime &ut, GeoLocation *geo, 0040 QWidget *parent) 0041 : KPageDialog(parent), selectedObject(o), Data(nullptr), DataComet(nullptr), 0042 Pos(nullptr), Links(nullptr), Adv(nullptr), 0043 Log(nullptr), m_user_data{ KStarsData::Instance()->getUserData(o->name()) } 0044 { 0045 #ifdef Q_OS_OSX 0046 setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); 0047 #endif 0048 setFaceType(Tabbed); 0049 setBackgroundRole(QPalette::Base); 0050 0051 titlePalette = palette(); 0052 titlePalette.setColor(backgroundRole(), palette().color(QPalette::Active, QPalette::Highlight)); 0053 titlePalette.setColor(foregroundRole(), palette().color(QPalette::Active, QPalette::HighlightedText)); 0054 0055 //Create thumbnail image 0056 Thumbnail.reset(new QPixmap(200, 200)); 0057 0058 setWindowTitle(i18nc("@title:window", "Object Details")); 0059 0060 // JM 2016-11-22: Do we really need a close button? 0061 //setStandardButtons(QDialogButtonBox::Close); 0062 setStandardButtons(QDialogButtonBox::NoButton); 0063 0064 createGeneralTab(); 0065 createPositionTab(ut, geo); 0066 createLinksTab(); 0067 createAdvancedTab(); 0068 createLogTab(); 0069 } 0070 0071 void DetailDialog::createGeneralTab() 0072 { 0073 Data = new DataWidget(this); 0074 addPage(Data, i18n("General")); 0075 0076 Data->Names->setPalette(titlePalette); 0077 0078 //Connections 0079 connect(Data->ObsListButton, SIGNAL(clicked()), this, SLOT(addToObservingList())); 0080 connect(Data->CenterButton, SIGNAL(clicked()), this, SLOT(centerMap())); 0081 #ifdef HAVE_INDI 0082 connect(Data->ScopeButton, SIGNAL(clicked()), this, SLOT(centerTelescope())); 0083 #else 0084 Data->ScopeButton->setEnabled(false); 0085 #endif 0086 connect(Data->Image, SIGNAL(clicked()), this, SLOT(updateThumbnail())); 0087 0088 // Stuff that should be visible only for specific types of objects 0089 Data->IllumLabel->setVisible(false); // Only shown for the moon 0090 Data->Illumination->setVisible(false); 0091 0092 Data->BVIndex->setVisible(false); // Only shown for stars 0093 Data->BVLabel->setVisible(false); 0094 0095 Data->CatalogLabel->setVisible(false); 0096 0097 //Show object thumbnail image 0098 showThumbnail(); 0099 0100 //Fill in the data fields 0101 //Contents depend on type of object 0102 QString objecttyp; 0103 0104 switch (selectedObject->type()) 0105 { 0106 case SkyObject::STAR: 0107 { 0108 StarObject *s = (StarObject *)selectedObject; 0109 0110 if (s->getHDIndex()) 0111 { 0112 Data->Names->setText( 0113 QString("%1, HD %2").arg(s->longname()).arg(s->getHDIndex())); 0114 } 0115 else 0116 { 0117 Data->Names->setText(s->longname()); 0118 } 0119 0120 objecttyp = i18n("%1 star", s->sptype()); 0121 Data->Magnitude->setText( 0122 i18nc("number in magnitudes", "%1 mag", 0123 QLocale().toString(s->mag(), 'f', 2))); //show to hundredth place 0124 0125 Data->BVLabel->setVisible(true); 0126 Data->BVIndex->setVisible(true); 0127 if (s->getBVIndex() < 30.) 0128 { 0129 Data->BVIndex->setText(QString::number(s->getBVIndex(), 'f', 2)); 0130 } 0131 0132 //The thumbnail image is empty, and isn't clickable for stars 0133 //Also, don't show the border around the Image QFrame. 0134 Data->Image->setFrameStyle(QFrame::NoFrame); 0135 disconnect(Data->Image, SIGNAL(clicked()), this, SLOT(updateThumbnail())); 0136 0137 //distance 0138 if (s->distance() > 2000. || s->distance() < 0.) // parallax < 0.5 mas 0139 { 0140 Data->Distance->setText( 0141 QString(i18nc("larger than 2000 parsecs", "> 2000 pc"))); 0142 } 0143 else if (s->distance() > 50.) //show to nearest integer 0144 { 0145 Data->Distance->setText(i18nc("number in parsecs", "%1 pc", 0146 QLocale().toString(s->distance(), 'f', 0))); 0147 } 0148 else if (s->distance() > 10.0) //show to tenths place 0149 { 0150 Data->Distance->setText(i18nc("number in parsecs", "%1 pc", 0151 QLocale().toString(s->distance(), 'f', 1))); 0152 } 0153 else //show to hundredths place 0154 { 0155 Data->Distance->setText(i18nc("number in parsecs", "%1 pc", 0156 QLocale().toString(s->distance(), 'f', 2))); 0157 } 0158 0159 //Note multiplicity/variability in angular size label 0160 Data->AngSizeLabel->setText(QString()); 0161 Data->AngSize->setText(QString()); 0162 Data->AngSizeLabel->setFont(Data->AngSize->font()); 0163 if (s->isMultiple() && s->isVariable()) 0164 { 0165 Data->AngSizeLabel->setText( 0166 i18nc("the star is a multiple star", "multiple") + ','); 0167 Data->AngSize->setText(i18nc("the star is a variable star", "variable")); 0168 } 0169 else if (s->isMultiple()) 0170 { 0171 Data->AngSizeLabel->setText( 0172 i18nc("the star is a multiple star", "multiple")); 0173 } 0174 else if (s->isVariable()) 0175 { 0176 Data->AngSizeLabel->setText( 0177 i18nc("the star is a variable star", "variable")); 0178 } 0179 0180 // Add a label to indicate proper motion 0181 double pmRA = s->pmRA(), pmDec = s->pmDec(); 0182 if (std::isfinite(pmRA) && std::isfinite(pmDec) && (pmRA != 0.0 || pmDec != 0.0)) 0183 { 0184 // we have data : abuse the illumination label to show it! 0185 Data->IllumLabel->setText(i18nc("Proper motion of a star", "Proper Motion:")); 0186 Data->Illumination->setText( 0187 i18nc( 0188 "The first arg is proper motion in right ascension and the second in the declination. The unit stands for milliarcsecond per year", 0189 "%1 %2 mas/yr", 0190 QLocale().toString(pmRA, 'f', (pmRA >= 100.0 ? 1 : 2)), 0191 QLocale().toString(pmDec, 'f', (pmDec >= 100.0 ? 1 : 2)) 0192 )); 0193 Data->IllumLabel->setVisible(true); 0194 Data->Illumination->setVisible(true); 0195 } 0196 0197 break; //end of stars case 0198 } 0199 case SkyObject::ASTEROID: //[fall through to planets] 0200 case SkyObject::COMET: //[fall through to planets] 0201 case SkyObject::MOON: //[fall through to planets] 0202 case SkyObject::PLANET: 0203 { 0204 KSPlanetBase *ps = dynamic_cast<KSPlanetBase *>(selectedObject); 0205 0206 if (!ps) 0207 break; 0208 0209 Data->Names->setText(ps->longname()); 0210 0211 //Type is "G5 star" for Sun 0212 if (ps->name() == i18n("Sun")) 0213 { 0214 objecttyp = i18n("G5 star"); 0215 } 0216 else if (ps->name() == i18n("Moon")) 0217 { 0218 objecttyp = ps->translatedName(); 0219 } 0220 else if (ps->name() == i18nc("Asteroid name (optional)", "Pluto") || 0221 ps->name() == i18nc("Asteroid name (optional)", "Ceres") || 0222 ps->name() == i18nc("Asteroid name (optional)", "Eris")) 0223 { 0224 objecttyp = i18n("Dwarf planet"); 0225 } 0226 else 0227 { 0228 objecttyp = ps->typeName(); 0229 } 0230 0231 //The moon displays illumination fraction and updateMag is called to calculate moon's current magnitude 0232 if (selectedObject->name() == i18n("Moon")) 0233 { 0234 Data->IllumLabel->setVisible(true); 0235 Data->Illumination->setVisible(true); 0236 Data->Illumination->setText(QString("%1 %").arg(QLocale().toString( 0237 ((KSMoon *)selectedObject)->illum() * 100., 'f', 0))); 0238 ((KSMoon *)selectedObject)->updateMag(); 0239 } 0240 0241 // JM: Shouldn't we use the calculated magnitude? Disabling the following 0242 /* 0243 if(selectedObject->type() == SkyObject::COMET){ 0244 Data->Magnitude->setText(i18nc("number in magnitudes", "%1 mag", 0245 QLocale().toString( ((KSComet *)selectedObject)->getTotalMagnitudeParameter(), 'f', 2))); //show to hundredth place 0246 0247 } 0248 else{*/ 0249 Data->Magnitude->setText( 0250 i18nc("number in magnitudes", "%1 mag", 0251 QLocale().toString(ps->mag(), 'f', 2))); //show to hundredth place 0252 //} 0253 0254 //Distance from Earth. The moon requires a unit conversion 0255 if (ps->name() == i18n("Moon")) 0256 { 0257 Data->Distance->setText( 0258 i18nc("distance in kilometers", "%1 km", 0259 QLocale().toString(ps->rearth() * AU_KM, 'f', 2))); 0260 } 0261 else 0262 { 0263 Data->Distance->setText(i18nc("distance in Astronomical Units", "%1 AU", 0264 QLocale().toString(ps->rearth(), 'f', 3))); 0265 } 0266 0267 //Angular size; moon and sun in arcmin, others in arcsec 0268 if (ps->angSize()) 0269 { 0270 if (ps->name() == i18n("Sun") || ps->name() == i18n("Moon")) 0271 { 0272 Data->AngSize->setText(i18nc( 0273 "angular size in arcminutes", "%1 arcmin", 0274 QLocale().toString( 0275 ps->angSize(), 'f', 0276 1))); // Needn't be a plural form because sun / moon will never contract to 1 arcminute 0277 } 0278 else 0279 { 0280 Data->AngSize->setText( 0281 i18nc("angular size in arcseconds", "%1 arcsec", 0282 QLocale().toString(ps->angSize() * 60.0, 'f', 1))); 0283 } 0284 } 0285 else 0286 { 0287 Data->AngSize->setText("--"); 0288 } 0289 0290 break; //end of planets/comets/asteroids case 0291 } 0292 case SkyObject::SUPERNOVA: 0293 { 0294 Supernova *sup = dynamic_cast<Supernova *>(selectedObject); 0295 0296 objecttyp = i18n("Supernova"); 0297 Data->Names->setText(sup->name()); 0298 if (sup->mag() < 99) 0299 Data->Magnitude->setText(i18nc("number in magnitudes", "%1 mag", 0300 QLocale().toString(sup->mag(), 'f', 2))); 0301 else 0302 Data->Magnitude->setText("--"); 0303 0304 Data->DistanceLabel->setVisible(false); 0305 Data->Distance->setVisible(false); 0306 0307 Data->AngSizeLabel->setVisible(false); 0308 Data->AngSize->setVisible(false); 0309 0310 QLabel *discoveryDateLabel = new QLabel(i18n("Discovery Date:"), this); 0311 QLabel *discoveryDate = new QLabel(sup->getDate(), this); 0312 Data->dataGridLayout->addWidget(discoveryDateLabel, 1, 0); 0313 Data->dataGridLayout->addWidget(discoveryDate, 1, 1); 0314 0315 QLabel *typeLabel = new QLabel(i18n("Type:"), this); 0316 QLabel *type = new QLabel(sup->getType(), this); 0317 Data->dataGridLayout->addWidget(typeLabel, 2, 0); 0318 Data->dataGridLayout->addWidget(type, 2, 1); 0319 0320 QLabel *hostGalaxyLabel = new QLabel(i18n("Host Galaxy:"), this); 0321 QLabel *hostGalaxy = new QLabel( 0322 sup->getHostGalaxy().isEmpty() ? "--" : sup->getHostGalaxy(), this); 0323 Data->dataGridLayout->addWidget(hostGalaxyLabel, 3, 0); 0324 Data->dataGridLayout->addWidget(hostGalaxy, 3, 1); 0325 0326 QLabel *redShiftLabel = new QLabel(i18n("Red Shift:"), this); 0327 QLabel *redShift = new QLabel( 0328 (sup->getRedShift() < 99) ? QString::number(sup->getRedShift(), 'f', 2) : 0329 QString("--"), 0330 this); 0331 Data->dataGridLayout->addWidget(redShiftLabel, 4, 0); 0332 Data->dataGridLayout->addWidget(redShift, 4, 1); 0333 0334 QLabel *urlLabel = new QLabel(i18n("URL:"), this); 0335 QLabel *url = new QLabel(QString("<a href=\"%1\">%1</a>").arg(sup->url()), this); 0336 url->setTextFormat(Qt::RichText); 0337 url->setTextInteractionFlags(Qt::TextBrowserInteraction); 0338 url->setOpenExternalLinks(true); 0339 Data->dataGridLayout->addWidget(urlLabel, 5, 0); 0340 Data->dataGridLayout->addWidget(url, 5, 1); 0341 0342 break; 0343 } 0344 default: //deep-sky objects 0345 { 0346 CatalogObject *dso = dynamic_cast<CatalogObject *>(selectedObject); 0347 0348 if (!dso) 0349 break; 0350 0351 //Show all names recorded for the object 0352 QStringList nameList; 0353 if (!dso->longname().isEmpty() && dso->longname() != dso->name()) 0354 { 0355 nameList.append(dso->translatedLongName()); 0356 } 0357 0358 nameList.append(dso->translatedName()); 0359 0360 if (!dso->translatedName2().isEmpty()) 0361 { 0362 nameList.append(dso->translatedName2()); 0363 } 0364 0365 Data->Names->setText(nameList.join(",")); 0366 0367 objecttyp = dso->typeName(); 0368 0369 if (dso->type() == SkyObject::RADIO_SOURCE) 0370 { 0371 Data->MagLabel->setText( 0372 i18nc("integrated flux at a frequency", "Flux(%1):", 1)); 0373 Data->Magnitude->setText(i18nc("integrated flux value", "%1 %2", 0374 QLocale().toString(dso->flux(), 'f', 1), 0375 "obs")); //show to tenths place 0376 } 0377 else if (std::isnan(dso->mag())) 0378 { 0379 Data->Magnitude->setText("--"); 0380 } 0381 else 0382 { 0383 Data->Magnitude->setText( 0384 i18nc("number in magnitudes", "%1 mag", 0385 QLocale().toString(dso->mag(), 'f', 1))); //show to tenths place 0386 } 0387 0388 //No distances at this point... 0389 Data->Distance->setText("--"); 0390 0391 Data->CatalogLabel->setVisible(true); 0392 Data->Catalog->setText(dso->getCatalog().name); 0393 0394 //Only show decimal place for small angular sizes 0395 if (dso->a() > 10.0) 0396 { 0397 Data->AngSize->setText(i18nc("angular size in arcminutes", "%1 arcmin", 0398 QLocale().toString(dso->a(), 'f', 0))); 0399 } 0400 else if (dso->a()) 0401 { 0402 Data->AngSize->setText(i18nc("angular size in arcminutes", "%1 arcmin", 0403 QLocale().toString(dso->a(), 'f', 1))); 0404 } 0405 else 0406 { 0407 Data->AngSize->setText("--"); 0408 } 0409 0410 break; 0411 } 0412 } 0413 0414 // Add specifics data 0415 switch (selectedObject->type()) 0416 { 0417 case SkyObject::ASTEROID: 0418 { 0419 KSAsteroid *ast = dynamic_cast<KSAsteroid *>(selectedObject); 0420 // Show same specifics data as comets 0421 DataComet = new DataCometWidget(this); 0422 Data->IncludeData->layout()->addWidget(DataComet); 0423 0424 // Perihelion 0425 DataComet->Perihelion->setText(i18nc("Distance in astronomical units", 0426 "%1 AU", 0427 QString::number(ast->getPerihelion()))); 0428 // Earth MOID 0429 if (ast->getEarthMOID() == 0) 0430 DataComet->EarthMOID->setText("--"); 0431 else 0432 DataComet->EarthMOID->setText( 0433 i18nc("Distance in astronomical units", "%1 AU", 0434 QString::number(ast->getEarthMOID()))); 0435 // Orbit ID 0436 DataComet->OrbitID->setText(ast->getOrbitID()); 0437 // Orbit Class 0438 DataComet->OrbitClass->setText(ast->getOrbitClass()); 0439 // NEO 0440 if (ast->isNEO()) 0441 DataComet->NEO->setText(i18n("Yes")); 0442 else 0443 DataComet->NEO->setText(i18n("No")); 0444 // Albedo 0445 if (ast->getAlbedo() == 0.0) 0446 DataComet->Albedo->setText("--"); 0447 else 0448 DataComet->Albedo->setText(QString::number(ast->getAlbedo())); 0449 // Diameter 0450 if (ast->getDiameter() == 0.0) 0451 DataComet->Diameter->setText("--"); 0452 else 0453 DataComet->Diameter->setText(i18nc("Diameter in kilometers", "%1 km", 0454 QString::number(ast->getDiameter()))); 0455 // Dimensions 0456 if (ast->getDimensions().isEmpty()) 0457 DataComet->Dimensions->setText("--"); 0458 else 0459 DataComet->Dimensions->setText( 0460 i18nc("Dimension in kilometers", "%1 km", ast->getDimensions())); 0461 // Rotation period 0462 if (ast->getRotationPeriod() == 0.0) 0463 DataComet->Rotation->setText("--"); 0464 else 0465 DataComet->Rotation->setText( 0466 i18nc("Rotation period in hours", "%1 h", 0467 QString::number(ast->getRotationPeriod()))); 0468 // Period 0469 if (ast->getPeriod() == 0.0) 0470 DataComet->Period->setText("--"); 0471 else 0472 DataComet->Period->setText(i18nc("Orbit period in years", "%1 y", 0473 QString::number(ast->getPeriod()))); 0474 break; 0475 } 0476 case SkyObject::COMET: 0477 { 0478 KSComet *com = dynamic_cast<KSComet *>(selectedObject); 0479 DataComet = new DataCometWidget(this); 0480 Data->IncludeData->layout()->addWidget(DataComet); 0481 0482 // Perihelion 0483 DataComet->Perihelion->setText(i18nc("Distance in astronomical units", 0484 "%1 AU", 0485 QString::number(com->getPerihelion()))); 0486 // Earth MOID 0487 if (com->getEarthMOID() == 0) 0488 DataComet->EarthMOID->setText("--"); 0489 else 0490 DataComet->EarthMOID->setText( 0491 i18nc("Distance in astronomical units", "%1 AU", 0492 QString::number(com->getEarthMOID()))); 0493 // Orbit ID 0494 DataComet->OrbitID->setText(com->getOrbitID()); 0495 // Orbit Class 0496 DataComet->OrbitClass->setText(com->getOrbitClass()); 0497 // NEO 0498 if (com->isNEO()) 0499 DataComet->NEO->setText(i18n("Yes")); 0500 else 0501 DataComet->NEO->setText(i18n("No")); 0502 // Albedo 0503 if (com->getAlbedo() == 0.0) 0504 DataComet->Albedo->setText("--"); 0505 else 0506 DataComet->Albedo->setText(QString::number(com->getAlbedo())); 0507 // Diameter 0508 if (com->getDiameter() == 0.0) 0509 DataComet->Diameter->setText("--"); 0510 else 0511 DataComet->Diameter->setText(i18nc("Diameter in kilometers", "%1 km", 0512 QString::number(com->getDiameter()))); 0513 // Dimensions 0514 if (com->getDimensions().isEmpty()) 0515 DataComet->Dimensions->setText("--"); 0516 else 0517 DataComet->Dimensions->setText( 0518 i18nc("Dimension in kilometers", "%1 km", com->getDimensions())); 0519 // Rotation period 0520 if (com->getRotationPeriod() == 0.0) 0521 DataComet->Rotation->setText("--"); 0522 else 0523 DataComet->Rotation->setText( 0524 i18nc("Rotation period in hours", "%1 h", 0525 QString::number(com->getRotationPeriod()))); 0526 // Period 0527 if (com->getPeriod() == 0.0) 0528 DataComet->Period->setText("--"); 0529 else 0530 DataComet->Period->setText(i18nc("Orbit period in years", "%1 y", 0531 QString::number(com->getPeriod()))); 0532 break; 0533 } 0534 } 0535 0536 //Common to all types: 0537 QString cname = KStarsData::Instance() 0538 ->skyComposite() 0539 ->constellationBoundary() 0540 ->constellationName(selectedObject); 0541 if (selectedObject->type() != SkyObject::CONSTELLATION) 0542 { 0543 cname = i18nc( 0544 "%1 type of sky object (planet, asteroid etc), %2 name of a constellation", 0545 "%1 in %2", objecttyp, cname); 0546 } 0547 Data->ObjectTypeInConstellation->setText(cname); 0548 } 0549 0550 void DetailDialog::createPositionTab(const KStarsDateTime &ut, GeoLocation *geo) 0551 { 0552 Pos = new PositionWidget(this); 0553 addPage(Pos, i18n("Position")); 0554 0555 Pos->CoordTitle->setPalette(titlePalette); 0556 Pos->RSTTitle->setPalette(titlePalette); 0557 KStarsData *data = KStarsData::Instance(); 0558 0559 //Coordinates Section: 0560 //Don't use KLocale::formatNumber() for the epoch string, 0561 //because we don't want a thousands-place separator! 0562 selectedObject->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false); 0563 QString sEpoch = QString::number(KStarsDateTime::jdToEpoch(selectedObject->getLastPrecessJD()), 'f', 1); 0564 //Replace the decimal point with localized decimal symbol 0565 sEpoch.replace('.', QLocale().decimalPoint()); // Is this necessary? -- asimha Oct 2016 0566 0567 /*qDebug() << Q_FUNC_INFO << (selectedObject->deprecess(data->updateNum())).ra0().toHMSString() 0568 << (selectedObject->deprecess(data->updateNum())).dec0().toDMSString();*/ 0569 //qDebug() << Q_FUNC_INFO << selectedObject->ra().toHMSString() << selectedObject->dec().toDMSString(); 0570 Pos->RALabel->setText(i18n("RA (%1):", sEpoch)); 0571 Pos->DecLabel->setText(i18n("DE (%1):", sEpoch)); 0572 Pos->RA->setText(selectedObject->ra().toHMSString(false, true)); 0573 Pos->Dec->setText(selectedObject->dec().toDMSString(false, false, true)); 0574 0575 selectedObject->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0576 0577 Pos->Az->setText(selectedObject->az().toDMSString()); 0578 dms a; 0579 0580 if (Options::useAltAz()) 0581 a = selectedObject->alt(); 0582 else 0583 a = selectedObject->altRefracted(); 0584 Pos->Alt->setText(a.toDMSString()); 0585 0586 // Display the RA0 and Dec0 for objects that are outside the solar system 0587 // 2017-09-10 JM: Exception added for asteroids and comets since we have J2000 for them. 0588 // Maybe others? 0589 Pos->RA0->setText(selectedObject->ra0().toHMSString(false, true)); 0590 Pos->Dec0->setText(selectedObject->dec0().toDMSString(false, false, true)); 0591 #if 0 0592 if (!selectedObject->isSolarSystem() || selectedObject->type() == SkyObject::COMET 0593 || selectedObject->type() == SkyObject::ASTEROID) 0594 { 0595 Pos->RA0->setText(selectedObject->ra0().toHMSString()); 0596 Pos->Dec0->setText(selectedObject->dec0().toDMSString()); 0597 } 0598 else 0599 { 0600 Pos->RA0->setText("--"); 0601 Pos->Dec0->setText("--"); 0602 } 0603 #endif 0604 0605 //Hour Angle can be negative, but dms HMS expressions cannot. 0606 //Here's a kludgy workaround: 0607 dms lst = geo->GSTtoLST(ut.gst()); 0608 dms ha(lst.Degrees() - selectedObject->ra().Degrees()); 0609 QChar sgn('+'); 0610 if (ha.Hours() > 12.0) 0611 { 0612 ha.setH(24.0 - ha.Hours()); 0613 sgn = '-'; 0614 } 0615 Pos->HA->setText(QString("%1%2").arg(sgn).arg(ha.toHMSString())); 0616 0617 //Airmass is approximated as the secant of the zenith distance, 0618 //equivalent to 1./sin(Alt). Beware of Inf at Alt=0! 0619 if (selectedObject->alt().Degrees() > 0.0) 0620 Pos->Airmass->setText(QLocale().toString(selectedObject->airmass(), 'f', 2)); 0621 else 0622 Pos->Airmass->setText("--"); 0623 0624 //Rise/Set/Transit Section: 0625 0626 //Prepare time/position variables 0627 QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time 0628 dms raz = selectedObject->riseSetTimeAz(ut, geo, true); //true = use rise time 0629 0630 //If transit time is before rise time, use transit time for tomorrow 0631 QTime tt = selectedObject->transitTime(ut, geo); 0632 dms talt = selectedObject->transitAltitude(ut, geo); 0633 if (tt < rt) 0634 { 0635 tt = selectedObject->transitTime(ut.addDays(1), geo); 0636 talt = selectedObject->transitAltitude(ut.addDays(1), geo); 0637 } 0638 0639 // JM 2021.09.14: Set time is already taken care of 0640 QTime st = selectedObject->riseSetTime(ut, geo, false); //false = use set time 0641 dms saz = selectedObject->riseSetTimeAz(ut, geo, false); //false = use set time 0642 // if (st < rt) 0643 // { 0644 // st = selectedObject->riseSetTime(ut.addDays(1), geo, false); //false = use set time 0645 // saz = selectedObject->riseSetTimeAz(ut.addDays(1), geo, false); //false = use set time 0646 // } 0647 0648 if (rt.isValid()) 0649 { 0650 Pos->TimeRise->setText(QString::asprintf("%02d:%02d", rt.hour(), rt.minute())); 0651 Pos->TimeSet->setText(QString::asprintf("%02d:%02d", st.hour(), st.minute())); 0652 Pos->AzRise->setText(raz.toDMSString()); 0653 Pos->AzSet->setText(saz.toDMSString()); 0654 } 0655 else 0656 { 0657 if (selectedObject->alt().Degrees() > 0.0) 0658 { 0659 Pos->TimeRise->setText(i18n("Circumpolar")); 0660 Pos->TimeSet->setText(i18n("Circumpolar")); 0661 } 0662 else 0663 { 0664 Pos->TimeRise->setText(i18n("Never rises")); 0665 Pos->TimeSet->setText(i18n("Never rises")); 0666 } 0667 0668 Pos->AzRise->setText(i18nc("Not Applicable", "N/A")); 0669 Pos->AzSet->setText(i18nc("Not Applicable", "N/A")); 0670 } 0671 0672 Pos->TimeTransit->setText(QString::asprintf("%02d:%02d", tt.hour(), tt.minute())); 0673 Pos->AltTransit->setText(talt.toDMSString()); 0674 0675 // Restore the position and other time-dependent parameters 0676 selectedObject->recomputeCoords(ut, geo); 0677 } 0678 0679 void DetailDialog::createLinksTab() 0680 { 0681 // don't create a link tab for an unnamed star 0682 if (selectedObject->name() == QString("star")) 0683 return; 0684 0685 Links = new LinksWidget(this); 0686 addPage(Links, i18n("Links")); 0687 0688 Links->InfoTitle->setPalette(titlePalette); 0689 Links->ImagesTitle->setPalette(titlePalette); 0690 0691 for (const auto &link : m_user_data.websites()) 0692 Links->InfoTitleList->addItem(i18nc("Image/info menu item (should be translated)", 0693 link.title.toLocal8Bit())); 0694 0695 //Links->InfoTitleList->setCurrentRow(0); 0696 0697 for (const auto &link : m_user_data.images()) 0698 Links->ImageTitleList->addItem(i18nc( 0699 "Image/info menu item (should be translated)", link.title.toLocal8Bit())); 0700 0701 // Signals/Slots 0702 connect(Links->ViewButton, SIGNAL(clicked()), this, SLOT(viewLink())); 0703 connect(Links->AddLinkButton, SIGNAL(clicked()), this, SLOT(addLink())); 0704 connect(Links->EditLinkButton, SIGNAL(clicked()), this, SLOT(editLinkDialog())); 0705 connect(Links->RemoveLinkButton, SIGNAL(clicked()), this, SLOT(removeLinkDialog())); 0706 0707 // When an item is selected in info list, selected items are cleared image list. 0708 connect(Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, 0709 SLOT(setCurrentLink(QListWidgetItem*))); 0710 connect(Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), 0711 Links->ImageTitleList, SLOT(clearSelection())); 0712 0713 // vice versa 0714 connect(Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, 0715 SLOT(setCurrentLink(QListWidgetItem*))); 0716 connect(Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), 0717 Links->InfoTitleList, SLOT(clearSelection())); 0718 0719 connect(Links->InfoTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(viewLink())); 0720 connect(Links->ImageTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(viewLink())); 0721 0722 connect(Links->InfoTitleList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons())); 0723 connect(Links->ImageTitleList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons())); 0724 0725 updateLists(); 0726 } 0727 0728 void DetailDialog::addLink() 0729 { 0730 if (!selectedObject) 0731 return; 0732 QPointer<AddLinkDialog> adialog = new AddLinkDialog(this, selectedObject->name()); 0733 QString entry; 0734 QFile file; 0735 0736 if (adialog->exec() == QDialog::Accepted) 0737 { 0738 const auto &success = KStarsData::Instance()->addToUserData( 0739 selectedObject->name(), 0740 SkyObjectUserdata::LinkData 0741 { 0742 adialog->desc(), QUrl(adialog->url()), 0743 (adialog->isImageLink()) ? SkyObjectUserdata::LinkData::Type::image : 0744 SkyObjectUserdata::LinkData::Type::website }); 0745 0746 if (!success.first) 0747 { 0748 KSNotification::sorry(success.second, i18n("Could not add the link.")); 0749 } 0750 } 0751 0752 updateLists(); 0753 delete adialog; 0754 } 0755 0756 void DetailDialog::createAdvancedTab() 0757 { 0758 // Don't create an adv tab for an unnamed star or if advinterface file failed loading 0759 // We also don't need adv dialog for solar system objects. 0760 if (selectedObject->name() == QString("star") || KStarsData::Instance()->avdTree().isEmpty() || 0761 selectedObject->type() == SkyObject::PLANET || selectedObject->type() == SkyObject::COMET || 0762 selectedObject->type() == SkyObject::ASTEROID) 0763 return; 0764 0765 Adv = new DatabaseWidget(this); 0766 addPage(Adv, i18n("Advanced")); 0767 0768 connect(Adv->ADVTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(viewADVData())); 0769 0770 populateADVTree(); 0771 } 0772 0773 void DetailDialog::createLogTab() 0774 { 0775 //Don't create a log tab for an unnamed star 0776 if (selectedObject->name() == QString("star")) 0777 return; 0778 0779 // Log Tab 0780 Log = new LogWidget(this); 0781 addPage(Log, i18n("Log")); 0782 0783 Log->LogTitle->setPalette(titlePalette); 0784 0785 const auto &log = m_user_data.userLog; 0786 0787 if (log.isEmpty()) 0788 Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.", 0789 selectedObject->translatedName())); 0790 else 0791 Log->UserLog->setText(log); 0792 0793 //Automatically save the log contents when the widget loses focus 0794 connect(Log->UserLog, SIGNAL(focusOut()), this, SLOT(saveLogData())); 0795 } 0796 0797 void DetailDialog::setCurrentLink(QListWidgetItem *it) 0798 { 0799 m_CurrentLink = it; 0800 } 0801 0802 void DetailDialog::viewLink() 0803 { 0804 QString URL; 0805 0806 if (m_CurrentLink == nullptr) 0807 return; 0808 0809 if (m_CurrentLink->listWidget() == Links->InfoTitleList) 0810 { 0811 URL = m_user_data.websites() 0812 .at(Links->InfoTitleList->row(m_CurrentLink)) 0813 .url.toString(); 0814 } 0815 else if (m_CurrentLink->listWidget() == Links->ImageTitleList) 0816 { 0817 URL = m_user_data.images() 0818 .at(Links->ImageTitleList->row(m_CurrentLink)) 0819 .url.toString(); 0820 } 0821 0822 if (!URL.isEmpty()) 0823 QDesktopServices::openUrl(QUrl(URL)); 0824 } 0825 0826 void DetailDialog::updateLists() 0827 { 0828 Links->InfoTitleList->clear(); 0829 Links->ImageTitleList->clear(); 0830 0831 for (const auto &element : m_user_data.websites()) 0832 Links->InfoTitleList->addItem(element.title); 0833 0834 for (const auto &element : m_user_data.images()) 0835 Links->ImageTitleList->addItem(element.title); 0836 0837 updateButtons(); 0838 } 0839 0840 void DetailDialog::updateButtons() 0841 { 0842 bool anyLink = false; 0843 if (!Links->InfoTitleList->selectedItems().isEmpty() || !Links->ImageTitleList->selectedItems().isEmpty()) 0844 anyLink = true; 0845 0846 // Buttons could be disabled if lists are initially empty, we enable and disable them here 0847 // depending on the current status of the list. 0848 Links->ViewButton->setEnabled(anyLink); 0849 Links->EditLinkButton->setEnabled(anyLink); 0850 Links->RemoveLinkButton->setEnabled(anyLink); 0851 } 0852 0853 void DetailDialog::editLinkDialog() 0854 { 0855 SkyObjectUserdata::Type type = SkyObjectUserdata::Type::image; 0856 int row = 0; 0857 0858 if (m_CurrentLink == nullptr) 0859 return; 0860 0861 QDialog editDialog(this); 0862 editDialog.setWindowTitle(i18nc("@title:window", "Edit Link")); 0863 0864 QVBoxLayout *mainLayout = new QVBoxLayout; 0865 0866 QFrame editFrame(&editDialog); 0867 0868 mainLayout->addWidget(&editFrame); 0869 0870 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0871 mainLayout->addWidget(buttonBox); 0872 connect(buttonBox, SIGNAL(accepted()), &editDialog, SLOT(accept())); 0873 connect(buttonBox, SIGNAL(rejected()), &editDialog, SLOT(reject())); 0874 0875 editDialog.setLayout(mainLayout); 0876 0877 if (m_CurrentLink->listWidget() == Links->InfoTitleList) 0878 { 0879 row = Links->InfoTitleList->row(m_CurrentLink); 0880 type = SkyObjectUserdata::Type::website; 0881 } 0882 else if (m_CurrentLink->listWidget() == Links->ImageTitleList) 0883 { 0884 row = Links->ImageTitleList->row(m_CurrentLink); 0885 type = SkyObjectUserdata::Type::image; 0886 } 0887 else 0888 return; 0889 0890 const auto ¤tItem = m_user_data.links.at(type).at(row); 0891 0892 QLineEdit editNameField(&editFrame); 0893 editNameField.setObjectName("nameedit"); 0894 editNameField.home(false); 0895 editNameField.setText(currentItem.title); 0896 QLabel editLinkURL(i18n("URL:"), &editFrame); 0897 QLineEdit editLinkField(&editFrame); 0898 editLinkField.setObjectName("urledit"); 0899 editLinkField.home(false); 0900 editLinkField.setText(currentItem.url.toString()); 0901 QVBoxLayout vlay(&editFrame); 0902 vlay.setObjectName("vlay"); 0903 QHBoxLayout editLinkLayout(&editFrame); 0904 editLinkLayout.setObjectName("editlinklayout"); 0905 editLinkLayout.addWidget(&editLinkURL); 0906 editLinkLayout.addWidget(&editLinkField); 0907 vlay.addWidget(&editNameField); 0908 vlay.addLayout(&editLinkLayout); 0909 0910 bool go(true); 0911 // If user presses cancel then skip the action 0912 if (editDialog.exec() != QDialog::Accepted) 0913 go = false; 0914 0915 // If nothing changed, skip th action 0916 if (editLinkField.text() == currentItem.url.toString() && 0917 editNameField.text() == currentItem.title) 0918 go = false; 0919 0920 if (go) 0921 { 0922 const auto &success = KStarsData::Instance()->editUserData( 0923 selectedObject->name(), row, 0924 { editNameField.text(), QUrl{ editLinkField.text() }, type }); 0925 0926 if (!success.first) 0927 KSNotification::sorry(success.second, i18n("Could not edit the entry.")); 0928 0929 // Set focus to the same item again 0930 if (type == SkyObjectUserdata::Type::website) 0931 Links->InfoTitleList->setCurrentRow(row); 0932 else 0933 Links->ImageTitleList->setCurrentRow(row); 0934 } 0935 0936 updateLists(); 0937 } 0938 0939 void DetailDialog::removeLinkDialog() 0940 { 0941 int row = 0; 0942 if (m_CurrentLink == nullptr) 0943 return; 0944 0945 SkyObjectUserdata::Type type; 0946 0947 if (m_CurrentLink->listWidget() == Links->InfoTitleList) 0948 { 0949 row = Links->InfoTitleList->row(m_CurrentLink); 0950 type = SkyObjectUserdata::Type::website; 0951 } 0952 else if (m_CurrentLink->listWidget() == Links->ImageTitleList) 0953 { 0954 row = Links->ImageTitleList->row(m_CurrentLink); 0955 type = SkyObjectUserdata::Type::image; 0956 } 0957 else 0958 return; 0959 0960 if (KMessageBox::warningContinueCancel( 0961 nullptr, 0962 i18n("Are you sure you want to remove the %1 link?", m_CurrentLink->text()), 0963 i18n("Delete Confirmation"), 0964 KStandardGuiItem::del()) != KMessageBox::Continue) 0965 return; 0966 0967 const auto &success = 0968 KStarsData::Instance()->deleteUserData(selectedObject->name(), row, type); 0969 0970 if (!success.first) 0971 KSNotification::sorry(success.second, i18n("Could not delete the entry.")); 0972 else 0973 updateLists(); 0974 } 0975 0976 void DetailDialog::populateADVTree() 0977 { 0978 QTreeWidgetItem *parent = nullptr; 0979 QTreeWidgetItem *temp = nullptr; 0980 0981 // We populate the tree iteratively, keeping track of parents as we go 0982 // This solution is more efficient than the previous recursion algorithm. 0983 foreach (ADVTreeData *item, KStarsData::Instance()->avdTree()) 0984 { 0985 switch (item->Type) 0986 { 0987 // Top Level 0988 case 0: 0989 temp = new QTreeWidgetItem(parent, QStringList(i18nc("Advanced URLs: description or category", 0990 item->Name.toLocal8Bit().data()))); 0991 if (parent == nullptr) 0992 Adv->ADVTree->addTopLevelItem(temp); 0993 parent = temp; 0994 0995 break; 0996 0997 // End of top level 0998 case 1: 0999 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 1011 void DetailDialog::viewADVData() 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); 1026 QDesktopServices::openUrl(QUrl(link)); 1027 return; 1028 } 1029 } 1030 } 1031 1032 QString 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 1078 void DetailDialog::saveLogData() 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 1087 void DetailDialog::addToObservingList() 1088 { 1089 KStarsData::Instance()->observingList()->slotAddObject(selectedObject); 1090 } 1091 1092 void DetailDialog::centerMap() 1093 { 1094 SkyMap::Instance()->setClickedObject(selectedObject); 1095 SkyMap::Instance()->slotCenter(); 1096 } 1097 1098 void DetailDialog::centerTelescope() 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 { 1126 if (KMessageBox::warningContinueCancel(nullptr, 1127 i18n("Danger! Viewing the Sun without adequate solar filters is dangerous and will result in permanent eye damage!")) 1128 == KMessageBox::Cancel) 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 1141 void DetailDialog::showThumbnail() 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()) 1164 .absoluteFilePath( 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(), 1180 Qt::KeepAspectRatio, Qt::FastTransformation); 1181 1182 Data->Image->setPixmap(*Thumbnail); 1183 } 1184 1185 void DetailDialog::updateThumbnail() 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 1233 DataWidget::DataWidget(QWidget *p) : QFrame(p) 1234 { 1235 setupUi(this); 1236 DataFrame->setBackgroundRole(QPalette::Base); 1237 } 1238 1239 DataCometWidget::DataCometWidget(QWidget *p) : QFrame(p) 1240 { 1241 setupUi(this); 1242 } 1243 1244 PositionWidget::PositionWidget(QWidget *p) : QFrame(p) 1245 { 1246 setupUi(this); 1247 CoordFrame->setBackgroundRole(QPalette::Base); 1248 RSTFrame->setBackgroundRole(QPalette::Base); 1249 } 1250 1251 LinksWidget::LinksWidget(QWidget *p) : QFrame(p) 1252 { 1253 setupUi(this); 1254 } 1255 1256 DatabaseWidget::DatabaseWidget(QWidget *p) : QFrame(p) 1257 { 1258 setupUi(this); 1259 } 1260 1261 LogWidget::LogWidget(QWidget *p) : QFrame(p) 1262 { 1263 setupUi(this); 1264 }