diff --git a/kstars/ekos/align/opsastrometryindexfiles.cpp b/kstars/ekos/align/opsastrometryindexfiles.cpp index 4095bc300..a1252e978 100644 --- a/kstars/ekos/align/opsastrometryindexfiles.cpp +++ b/kstars/ekos/align/opsastrometryindexfiles.cpp @@ -1,507 +1,513 @@ #include "opsastrometryindexfiles.h" #include "align.h" #include "kstars.h" #include "Options.h" #include #include #include #include namespace Ekos { OpsAstrometryIndexFiles::OpsAstrometryIndexFiles(Align *parent) : QDialog(KStars::Instance()) { setupUi(this); downloadSpeed = 100; actualdownloadSpeed = downloadSpeed; alignModule = parent; manager = new QNetworkAccessManager(); //Get a pointer to the KConfigDialog // m_ConfigDialog = KConfigDialog::exists( "alignsettings" ); connect(openIndexFileDirectory, SIGNAL(clicked()), this, SLOT(slotOpenIndexFileDirectory())); astrometryIndex[2.8] = "00"; astrometryIndex[4.0] = "01"; astrometryIndex[5.6] = "02"; astrometryIndex[8] = "03"; astrometryIndex[11] = "04"; astrometryIndex[16] = "05"; astrometryIndex[22] = "06"; astrometryIndex[30] = "07"; astrometryIndex[42] = "08"; astrometryIndex[60] = "09"; astrometryIndex[85] = "10"; astrometryIndex[120] = "11"; astrometryIndex[170] = "12"; astrometryIndex[240] = "13"; astrometryIndex[340] = "14"; astrometryIndex[480] = "15"; astrometryIndex[680] = "16"; astrometryIndex[1000] = "17"; astrometryIndex[1400] = "18"; astrometryIndex[2000] = "19"; QList checkboxes = findChildren(); for (auto &checkBox : checkboxes) { connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(downloadOrDeleteIndexFiles(bool))); } QList progressBars = findChildren(); QList qLabels = findChildren(); QList qButtons = findChildren(); for (auto &bar : progressBars) { - bar->setVisible(false); - bar->setTextVisible(false); + if(bar->objectName().contains("progress")) + { + bar->setVisible(false); + bar->setTextVisible(false); + } } for (auto &button : qButtons) { - button->setVisible(false); + if(button->objectName().contains("cancel")) + { + button->setVisible(false); + } } for (QLabel * label: qLabels) { if(label->text().contains("info")||label->text().contains("perc")) { label->setVisible(false); } } } void OpsAstrometryIndexFiles::showEvent(QShowEvent *) { slotUpdate(); } void OpsAstrometryIndexFiles::slotUpdate() { double fov_w, fov_h, fov_pixscale; // Values in arcmins. Scale in arcsec per pixel alignModule->getFOVScale(fov_w, fov_h, fov_pixscale); double fov_check = qMax(fov_w, fov_h); FOVOut->setText(QString("%1' x %2'").arg(QString::number(fov_w, 'f', 2), QString::number(fov_h, 'f', 2))); QString astrometryDataDir; if (getAstrometryDataDir(astrometryDataDir) == false) return; indexLocation->setText(astrometryDataDir); QStringList nameFilter("*.fits"); QDir directory(astrometryDataDir); QStringList indexList = directory.entryList(nameFilter); for (auto &indexName : indexList) { if(fileCountMatches(directory,indexName)){ indexName = indexName.replace('-', '_').left(10); QCheckBox *indexCheckBox = findChild(indexName); if (indexCheckBox) indexCheckBox->setChecked(true); } } QList checkboxes = findChildren(); for (auto &checkBox : checkboxes) { checkBox->setIcon(QIcon(":/icons/astrometry-optional.svg")); checkBox->setToolTip(i18n("Optional")); } float last_skymarksize = 2; for (auto &skymarksize : astrometryIndex.keys()) { if ((skymarksize >= 0.40 * fov_check && skymarksize <= 0.9 * fov_check) || (fov_check > last_skymarksize && fov_check < skymarksize)) { QString indexName1 = "index_41" + astrometryIndex.value(skymarksize); QString indexName2 = "index_42" + astrometryIndex.value(skymarksize); QCheckBox *indexCheckBox1 = findChild(indexName1); QCheckBox *indexCheckBox2 = findChild(indexName2); if (indexCheckBox1) { indexCheckBox1->setIcon(QIcon(":/icons/astrometry-required.svg")); indexCheckBox1->setToolTip(i18n("Required")); } if (indexCheckBox2) { indexCheckBox2->setIcon(QIcon(":/icons/astrometry-required.svg")); indexCheckBox2->setToolTip(i18n("Required")); } } else if (skymarksize >= 0.10 * fov_check && skymarksize <= fov_check) { QString indexName1 = "index_41" + astrometryIndex.value(skymarksize); QString indexName2 = "index_42" + astrometryIndex.value(skymarksize); QCheckBox *indexCheckBox1 = findChild(indexName1); QCheckBox *indexCheckBox2 = findChild(indexName2); if (indexCheckBox1) { indexCheckBox1->setIcon(QIcon(":/icons/astrometry-recommended.svg")); indexCheckBox1->setToolTip(i18n("Recommended")); } if (indexCheckBox2) { indexCheckBox2->setIcon(QIcon(":/icons/astrometry-recommended.svg")); indexCheckBox2->setToolTip(i18n("Recommended")); } } last_skymarksize = skymarksize; } } bool OpsAstrometryIndexFiles::fileCountMatches(QDir directory, QString indexName){ QString indexNameMatch = indexName.left(10) + "*.fits"; QStringList list = directory.entryList(QStringList(indexNameMatch)); int count=0; if(indexName.contains("4207")||indexName.contains("4206")||indexName.contains("4205")) count = 12; else if(indexName.contains("4204")||indexName.contains("4203")||indexName.contains("4202")||indexName.contains("4201")||indexName.contains("4200")) count = 48; else count = 1; return list.count()==count; } void OpsAstrometryIndexFiles::slotOpenIndexFileDirectory() { QString astrometryDataDir; if (getAstrometryDataDir(astrometryDataDir) == false) return; QUrl path = QUrl::fromLocalFile(astrometryDataDir); QDesktopServices::openUrl(path); } bool OpsAstrometryIndexFiles::getAstrometryDataDir(QString &dataDir) { QString confPath; if (Options::astrometryConfFileIsInternal()) confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; else confPath = Options::astrometryConfFile(); QFile confFile(confPath); if (confFile.open(QIODevice::ReadOnly) == false) { KMessageBox::error(0, i18n("Astrometry configuration file corrupted or missing: %1\nPlease set the " "configuration file full path in INDI options.", Options::astrometryConfFile())); return false; } QTextStream in(&confFile); QString line; while (!in.atEnd()) { line = in.readLine(); if (line.isEmpty() || line.startsWith('#')) continue; line = line.trimmed(); if (line.startsWith(QLatin1String("add_path"))) { dataDir = line.mid(9).trimmed(); return true; } } KMessageBox::error(0, i18n("Unable to find data dir in astrometry configuration file.")); return false; } bool OpsAstrometryIndexFiles::astrometryIndicesAreAvailable() { QNetworkReply *response = manager->get(QNetworkRequest(QUrl("http://broiler.astrometry.net"))); QTimer timeout(this); timeout.setInterval(5000); timeout.setSingleShot(true); timeout.start(); while (!response->isFinished()) { if (!timeout.isActive()) { response->deleteLater(); return false; } qApp->processEvents(); } timeout.stop(); bool wasSuccessful = (response->error() == QNetworkReply::NoError); response->deleteLater(); return wasSuccessful; } void OpsAstrometryIndexFiles::downloadIndexFile(const QString &URL, const QString &fileN, QCheckBox *checkBox, int currentIndex, int maxIndex, double fileSize) { QTime downloadTime; downloadTime.start(); QString indexString = QString::number(currentIndex); if (currentIndex < 10) indexString = '0' + indexString; QString indexSeriesName = checkBox->text().remove('&'); QProgressBar *indexDownloadProgress = findChild(indexSeriesName.replace('-', '_').left(10) + "_progress"); QLabel *indexDownloadInfo = findChild(indexSeriesName.replace('-', '_').left(10) + "_info"); QPushButton *indexDownloadCancel = findChild(indexSeriesName.replace('-', '_').left(10) + "_cancel"); QLabel *indexDownloadPerc = findChild(indexSeriesName.replace('-', '_').left(10) + "_perc"); setDownloadInfoVisible(indexSeriesName, checkBox, true); if(indexDownloadInfo){ if (indexDownloadProgress && maxIndex > 0) indexDownloadProgress->setValue(currentIndex*100 / maxIndex); indexDownloadInfo->setText("(" + QString::number(currentIndex) + '/' + QString::number(maxIndex + 1) + ") "); } QString indexURL = URL; indexURL.replace('*', indexString); QNetworkReply *response = manager->get(QNetworkRequest(QUrl(indexURL))); //Shut it down after too much time elapses. //If the filesize is less than 4 MB, it sets the timeout for 1 minute or 60000 s. //If it's larger, it assumes a bad download rate of 1 Mbps (100 bytes/ms) //and the calculation estimates the time in milliseconds it would take to download. int timeout=60000; if(fileSize>4000000) timeout=fileSize/downloadSpeed; //qDebug()<<"Filesize: "<< fileSize << ", timeout: " << timeout; QMetaObject::Connection *cancelConnection = new QMetaObject::Connection(); QMetaObject::Connection *replyConnection = new QMetaObject::Connection(); QMetaObject::Connection *percentConnection = new QMetaObject::Connection(); if(indexDownloadPerc){ *percentConnection=connect(response,&QNetworkReply::downloadProgress, [=](qint64 bytesReceived, qint64 bytesTotal){ if (indexDownloadProgress){ indexDownloadProgress->setValue(bytesReceived); indexDownloadProgress->setMaximum(bytesTotal); } indexDownloadPerc->setText(QString::number(bytesReceived * 100 / bytesTotal) + '%'); }); } QTimer::singleShot(timeout, response, [=]() { KMessageBox::error(0, i18n("Download Timed out. Either the network is not fast enough, the file is not accessible, or you aren't connected.")); disconnectDownload(cancelConnection,replyConnection,percentConnection); if(response){ response->abort(); response->deleteLater(); } setDownloadInfoVisible(indexSeriesName, checkBox, false); }); *cancelConnection=connect(indexDownloadCancel, &QPushButton::clicked, [=](){ qDebug() << "Download Cancelled."; disconnectDownload(cancelConnection,replyConnection,percentConnection); if(response){ response->abort(); response->deleteLater(); } setDownloadInfoVisible(indexSeriesName, checkBox, false); }); *replyConnection=connect(response, &QNetworkReply::finished, this, [=]() { if(response){ disconnectDownload(cancelConnection,replyConnection,percentConnection); setDownloadInfoVisible(indexSeriesName, checkBox, false); response->deleteLater(); if (response->error() != QNetworkReply::NoError) return; QByteArray responseData = response->readAll(); QString indexFileN = fileN; indexFileN.replace('*', indexString); QFile file(indexFileN); if (QFileInfo(QFileInfo(file).path()).isWritable()) { if (!file.open(QIODevice::WriteOnly)) { KMessageBox::error(0, i18n("File Write Error")); slotUpdate(); return; } else { file.write(responseData.data(), responseData.size()); file.close(); int downloadedFileSize = QFileInfo(file).size(); int dtime=downloadTime.elapsed(); actualdownloadSpeed=(actualdownloadSpeed+(downloadedFileSize/dtime))/2; qDebug()<<"Filesize: "<< downloadedFileSize<<", time: "<exec()) { QMessageBox::information( this, "Error", QString("KAuth returned an error code: %1 %2").arg(job->error()).arg(job->errorString())); slotUpdate(); return; } #endif } if (currentIndex == maxIndex) { slotUpdate(); } else downloadIndexFile(URL, fileN, checkBox, currentIndex + 1, maxIndex, fileSize); } }); } void OpsAstrometryIndexFiles::setDownloadInfoVisible(QString indexSeriesName, QCheckBox *checkBox, bool set){ QProgressBar *indexDownloadProgress = findChild(indexSeriesName.replace('-', '_').left(10) + "_progress"); QLabel *indexDownloadInfo = findChild(indexSeriesName.replace('-', '_').left(10) + "_info"); QPushButton *indexDownloadCancel = findChild(indexSeriesName.replace('-', '_').left(10) + "_cancel"); QLabel *indexDownloadPerc = findChild(indexSeriesName.replace('-', '_').left(10) + "_perc"); if (indexDownloadProgress) indexDownloadProgress->setVisible(set); if (indexDownloadInfo) indexDownloadInfo->setVisible(set); if (indexDownloadCancel) indexDownloadCancel->setVisible(set); if (indexDownloadPerc) indexDownloadPerc->setVisible(set); checkBox->setEnabled(!set); } void OpsAstrometryIndexFiles::disconnectDownload(QMetaObject::Connection *cancelConnection,QMetaObject::Connection *replyConnection,QMetaObject::Connection *percentConnection){ if(cancelConnection) disconnect(*cancelConnection); if(replyConnection) disconnect(*replyConnection); if(percentConnection) disconnect(*percentConnection); } void OpsAstrometryIndexFiles::downloadOrDeleteIndexFiles(bool checked) { QCheckBox *checkBox = (QCheckBox *)QObject::sender(); QString astrometryDataDir; if (getAstrometryDataDir(astrometryDataDir) == false) return; if (checkBox) { QString indexSeriesName = checkBox->text().remove('&'); QString filePath = astrometryDataDir + '/' + indexSeriesName; QString fileNumString = indexSeriesName.mid(8, 2); int indexFileNum = fileNumString.toInt(); if (checked) { checkBox->setChecked(!checked); if (astrometryIndicesAreAvailable()) { QString URL; if (indexSeriesName.startsWith(QLatin1String("index-41"))) URL = "http://broiler.astrometry.net/~dstn/4100/" + indexSeriesName; else if (indexSeriesName.startsWith(QLatin1String("index-42"))) URL = "http://broiler.astrometry.net/~dstn/4200/" + indexSeriesName; int maxIndex = 0; if (indexFileNum < 8 && URL.contains("*")) { maxIndex = 11; if (indexFileNum < 5) maxIndex = 47; } double fileSize=1E11*qPow(astrometryIndex.key(fileNumString),-1.909); //This estimates the file size based on skymark size obtained from the index number. if(maxIndex!=0) fileSize/=maxIndex; //FileSize is divided between multiple files for some index series. downloadIndexFile(URL, filePath, checkBox, 0, maxIndex,fileSize); } else { KMessageBox::sorry(0, i18n("Could not contact Astrometry Index Server: broiler.astrometry.net")); } } else { if (KMessageBox::Continue == KMessageBox::warningContinueCancel( NULL, "Are you sure you want to delete these index files? " + indexSeriesName, i18n("Delete File(s)"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "delete_index_files_warning")) { if (QFileInfo(astrometryDataDir).isWritable()) { QStringList nameFilter("*.fits"); QDir directory(astrometryDataDir); QStringList indexList = directory.entryList(nameFilter); for (auto &fileName : indexList) { if (fileName.contains(indexSeriesName.left(10))) { if (!directory.remove(fileName)) { KMessageBox::error(0, i18n("File Delete Error")); slotUpdate(); return; } } } } else { #ifdef Q_OS_OSX KMessageBox::error(0, i18n("Astrometry Folder Permissions Error")); slotUpdate(); #else KAuth::Action action(QStringLiteral("org.kde.kf5auth.kstars.removeindexfileset")); action.setHelperId(QStringLiteral("org.kde.kf5auth.kstars")); action.setArguments( QVariantMap({ { "indexSetName", indexSeriesName }, { "astrometryDataDir", astrometryDataDir } })); KAuth::ExecuteJob *job = action.execute(); if (!job->exec()) QMessageBox::information( this, "Error", QString("KAuth returned an error code: %1 %2").arg(job->error()).arg(job->errorString())); #endif } } } } } } diff --git a/kstars/ekos/align/opsastrometryindexfiles.ui b/kstars/ekos/align/opsastrometryindexfiles.ui index 2f651a156..f20fdf9b2 100644 --- a/kstars/ekos/align/opsastrometryindexfiles.ui +++ b/kstars/ekos/align/opsastrometryindexfiles.ui @@ -1,3821 +1,3824 @@ OpsAstrometryIndexFiles 0 0 768 852 Dialog li { background: url(:/icons/astrometry-required.svg) no-repeat left top; } - <html><head/><body><p><span style=" font-weight:600;">Offline</span> astrometry.net solver requires index files in order to solve an image. The following list provides a complete list of the index files, along with recommended index files to install given current CCD Field of View. Installed index files are checked. Next to each index file is an icon that represents the following:</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Offline</span> astrometry.net solver requires index files in order to solve an image. Please see the Astrometrty.net <a href="http://astrometry.net/doc/readme.html"><span style=" text-decoration: underline; color:#0000ff;">README</span></a> for details. The following list provides a complete list of the index files, along with recommended index files to install given the current CCD Field of View. Installed index files are checked. Next to each index file is an icon that represents the following:</p></body></html> true + + true + false 32 32 32 32 <html><head/><body><p>This index file is required and must be installed for the solver to work correctly.</p></body></html> :/icons/astrometry-required.svg true <html><head/><body><p>This index file is required and must be installed for the solver to work correctly.</p></body></html> Required Qt::Horizontal 13 20 false 32 32 32 32 <html><head/><body><p>This index file is recommended. Installing the index file might help in improving the solver.</p></body></html> :/icons/astrometry-recommended.svg true <html><head/><body><p>This index file is recommended. Installing the index file might help in improving the solver.</p></body></html> Recommended Qt::Horizontal 13 20 false 32 32 32 32 <html><head/><body><p>This index file is not required.</p></body></html> :/icons/astrometry-optional.svg true <html><head/><body><p>This index file is not required.</p></body></html> Optional <html><head/><body><p>This displays the path to the folder for the Astrometry Index Files on your computer.</p></body></html> Index Files Location: false <html><head/><body><p>This displays the path to the folder for the Astrometry Index Files on your computer.</p></body></html> <html><head/><body><p>This button will open the Astrometry Index File folder on your filesystem so that you can see where it is located and copy files into it if needed.</p></body></html> Open <html><head/><body><p>This displays the current CCD field of view that will be used to calculate which index files are needed.</p></body></html> Current CCD FOV: true Qt::Horizontal 40 20 Index Files index-4210.fits index-4208.fits (arcminutes) SkyMark 0 0 0 0 75 20 0 100 0 0 0 0 0 75 20 0 100 0 (242 K) 680' - 1000' 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X Wide Fields Qt::AlignCenter (160 K) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4115.fits index-4111.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (2.1 M) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4107.fits 0 5.6' - 8.0' 0 0 0 0 75 20 0 100 0 info (129 K) (208 K) perc index-4201-*.fits index-4207-*.fits (1.3 M) 0 4.0' - 5.6' 0 0 0 0 75 20 0 100 0 info (20 M) (4.8 G) 480' - 680' (723 K) perc 0 16' - 22' 0 0 0 0 75 20 0 100 0 info (9.7 M) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 120' - 170' 0 0 0 0 75 20 0 100 0 perc 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X perc Fields Qt::AlignCenter index-4218.fits (1.2 G) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (39 M) perc index-4119.fits index-4202-*.fits Tycho2 Catalog Qt::AlignCenter (24 M) (78 M) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X perc index-4117.fits 0 8' - 11' 0 0 0 0 75 20 0 100 0 info index-4212.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4116.fits (2.6 M) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (141 K) Narrow - Medium Qt::AlignCenter index-4203-*.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4108.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4217.fits 1400' - 2000' 170' - 240' (624 M) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4214.fits 240' - 340' (312 M) (filesize) Qt::AlignCenter 340' - 480' 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (183 K) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 42' - 60' 0 0 0 0 75 20 0 100 0 perc 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (4 M) index-4206-*.fits (8.8 G) index-4109.fits index-4113.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 2.8' - 4.0' 0 0 0 0 75 20 0 100 0 info (156 M) index-4205-*.fits 0 0 0 0 75 20 0 100 0 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4118.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4213.fits 0 2.0' - 2.8' 0 0 0 0 75 20 0 100 0 info index-4219.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4204-*.fits 0 0 0 0 75 20 0 100 0 2Mass Catalog Qt::AlignCenter Diameters 0 11' - 16' 0 0 0 0 75 20 0 100 0 info index-4215.fits 0 0 0 0 75 20 0 100 0 0 0 0 0 75 20 0 100 0 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (13.6 G) index-4200-*.fits 0 60' - 85' 0 0 0 0 75 20 0 100 0 perc index-4110.fits (1 M) index-4114.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X perc (157 M) (filesize) 0 22' - 30' 0 0 0 0 75 20 0 100 0 info (399 K) (582 K) 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X (90 M) index-4216.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X 0 30' - 42' 0 0 0 0 75 20 0 100 0 perc index-4211.fits 0 0 15 15 15 15 255 0 0 255 0 0 148 148 148 X index-4209.fits (332 K) (2.5 G) index-4112.fits (7.6 M) (5.1 M) (47 M) 0 85' - 120' 0 0 0 0 75 20 0 100 0 perc 1000' - 1400'