2#include "opsastrometryindexfiles.h"
8#include "ksnotification.h"
10#include <KConfigDialog>
13#include <QDesktopServices>
17OpsAstrometryIndexFiles::OpsAstrometryIndexFiles(
Align *parent) : QDialog(KStars::Instance())
22 actualdownloadSpeed = downloadSpeed;
26 indexURL->setText(
"http://data.astrometry.net/");
30 connect(openIndexFileDirectory, SIGNAL(clicked()),
this, SLOT(slotOpenIndexFileDirectory()));
32 astrometryIndex[2.8] =
"00";
33 astrometryIndex[4.0] =
"01";
34 astrometryIndex[5.6] =
"02";
35 astrometryIndex[8] =
"03";
36 astrometryIndex[11] =
"04";
37 astrometryIndex[16] =
"05";
38 astrometryIndex[22] =
"06";
39 astrometryIndex[30] =
"07";
40 astrometryIndex[42] =
"08";
41 astrometryIndex[60] =
"09";
42 astrometryIndex[85] =
"10";
43 astrometryIndex[120] =
"11";
44 astrometryIndex[170] =
"12";
45 astrometryIndex[240] =
"13";
46 astrometryIndex[340] =
"14";
47 astrometryIndex[480] =
"15";
48 astrometryIndex[680] =
"16";
49 astrometryIndex[1000] =
"17";
50 astrometryIndex[1400] =
"18";
51 astrometryIndex[2000] =
"19";
56 &OpsAstrometryIndexFiles::slotUpdate);
58 for (
auto &checkBox : checkboxes)
67 for (
auto &bar : progressBars)
69 if(bar->objectName().contains(
"progress"))
71 bar->setVisible(
false);
72 bar->setTextVisible(
false);
76 for (
auto &button : qButtons)
78 if(button->objectName().contains(
"cancel"))
80 button->setVisible(
false);
84 for (
QLabel * label : qLabels)
88 label->setVisible(
false);
100 addDirectoryToList(dir);
104 if(indexLocations->currentIndex() != 0)
105 removeDirectoryFromList(indexLocations->currentText());
111void OpsAstrometryIndexFiles::showEvent(
QShowEvent *)
113 updateIndexDirectoryList();
117void OpsAstrometryIndexFiles::updateIndexDirectoryList()
121 QStringList astrometryDataDirs = KSUtils::getAstrometryDataDirs();
123 indexLocations->clear();
124 if(astrometryDataDirs.
count() > 1)
125 indexLocations->addItem(
"All Sources");
126 indexLocations->addItems(astrometryDataDirs);
130void OpsAstrometryIndexFiles::addDirectoryToList(
QString directory)
137 QStringList indexFileDirs = Options::astrometryIndexFolderList();
138 if(indexFileDirs.
contains(directoryPath))
140 indexFileDirs.
append(directoryPath);
141 Options::setAstrometryIndexFolderList(indexFileDirs);
142 updateIndexDirectoryList();
145void OpsAstrometryIndexFiles::removeDirectoryFromList(
QString directory)
147 QStringList indexFileDirs = Options::astrometryIndexFolderList();
148 if(indexFileDirs.
contains(directory))
151 Options::setAstrometryIndexFolderList(indexFileDirs);
152 updateIndexDirectoryList();
156void OpsAstrometryIndexFiles::downloadSingleIndexFile(
const QString &indexFileName)
158 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
159 if (astrometryDataDirs.
isEmpty())
161 KSNotification::sorry(
i18n(
"No index file directories configured."),
i18n(
"Error"), 10);
166 if (astrometryDataDirs.
count() > 1)
170 for (
const QString &dir : astrometryDataDirs)
173 if (directory.exists())
175 if (fileCountMatches(directory, indexFileName))
182 QString astrometryDataDir = findFirstWritableDir();
183 if (astrometryDataDir.
isEmpty())
185 KSNotification::sorry(
i18n(
"No writable index file directory found."),
i18n(
"Error"), 10);
189 if (!astrometryIndicesAreAvailable())
191 KSNotification::sorry(
i18n(
"Could not contact Astrometry Index Server."),
i18n(
"Error"), 10);
196 if (indexURL->text().endsWith(
"/"))
197 BASE_URL = indexURL->text();
199 BASE_URL = indexURL->text() +
"/";
203 URL = BASE_URL +
"4100/" + indexFileName;
204 else if (indexFileName.startsWith(
QLatin1String(
"index-42")))
205 URL = BASE_URL +
"4200/" + indexFileName;
206 else if (indexFileName.startsWith(
QLatin1String(
"index-52")))
207 URL =
"https://portal.nersc.gov/project/cosmo/temp/dstn/index-5200/LITE/" + indexFileName;
211 QString filePath = astrometryDataDir +
'/' + indexFileName;
212 QString fileNumString = indexFileName.
mid(8, 2);
215 QString indexName = indexFileName;
217 indexName = indexName.
left(10);
218 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
222 double fileSize = 1E11 * qPow(astrometryIndex.key(fileNumString), -1.909);
223 downloadIndexFile(URL, filePath, indexFileName, 0, 0, fileSize);
229void OpsAstrometryIndexFiles::slotUpdate()
233 for (
auto &checkBox : checkboxes)
235 checkBox->setChecked(
false);
238 if(indexLocations->count() == 0)
241 double fov_w, fov_h, fov_pixscale;
244 alignModule->getFOVScale(fov_w, fov_h, fov_pixscale);
246 double fov_check = qMax(fov_w, fov_h);
252 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
254 bool allDirsSelected = (indexLocations->currentIndex() == 0 && astrometryDataDirs.
count() > 1);
255 bool folderIsWriteable;
261 folderDetails->setText(
i18n(
"Downloads Disabled, this is not a directory, it is a list of all index files."));
262 folderIsWriteable =
false;
263 astrometryDataDirsToIndex = astrometryDataDirs;
264 openIndexFileDirectory->setEnabled(
false);
268 QString folderPath = indexLocations->currentText();
270 if(folderIsWriteable)
271 folderDetails->setText(
i18n(
"Downloads Enabled, the directory exists and is writeable."));
273 folderDetails->setText(
i18n(
"Downloads Disabled, directory permissions issue."));
275 folderDetails->setText(
i18n(
"Downloads Disabled, directory does not exist."));
276 astrometryDataDirsToIndex << folderPath;
277 openIndexFileDirectory->setEnabled(
true);
279 folderDetails->setCursorPosition(0);
283 for(
auto &astrometryDataDir : astrometryDataDirsToIndex)
285 QDir directory(astrometryDataDir);
286 QStringList indexList = directory.entryList(nameFilter);
288 for (
auto &indexName : indexList)
290 if (fileCountMatches(directory, indexName))
293 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
300 for (
auto &checkBox : checkboxes)
302 checkBox->setEnabled(folderIsWriteable);
303 checkBox->setIcon(
QIcon(
":/icons/astrometry-optional.svg"));
304 checkBox->setToolTip(
i18n(
"Optional"));
305 checkBox->setStyleSheet(
"");
308 float last_skymarksize = 2;
310 for (
auto &skymarksize : astrometryIndex.keys())
312 QString indexName1 =
"index_41" + astrometryIndex.value(skymarksize);
313 QString indexName2 =
"index_42" + astrometryIndex.value(skymarksize);
314 QString indexName3 =
"index_52" + astrometryIndex.value(skymarksize);
315 QCheckBox *indexCheckBox1 = findChild<QCheckBox *>(indexName1);
316 QCheckBox *indexCheckBox2 = findChild<QCheckBox *>(indexName2);
317 QCheckBox *indexCheckBox3 = findChild<QCheckBox *>(indexName3);
318 if ((skymarksize >= 0.40 * fov_check && skymarksize <= 0.9 * fov_check) ||
319 (fov_check > last_skymarksize && fov_check < skymarksize))
323 indexCheckBox1->
setIcon(
QIcon(
":/icons/astrometry-required.svg"));
328 indexCheckBox2->
setIcon(
QIcon(
":/icons/astrometry-required.svg"));
333 indexCheckBox3->
setIcon(
QIcon(
":/icons/astrometry-required.svg"));
337 else if (skymarksize >= 0.10 * fov_check && skymarksize <= fov_check)
341 indexCheckBox1->
setIcon(
QIcon(
":/icons/astrometry-recommended.svg"));
346 indexCheckBox2->
setIcon(
QIcon(
":/icons/astrometry-recommended.svg"));
351 indexCheckBox3->
setIcon(
QIcon(
":/icons/astrometry-recommended.svg"));
356 last_skymarksize = skymarksize;
362 for(
QString astrometryDataDir : astrometryDataDirs)
364 QDir directory(astrometryDataDir);
365 QStringList indexList = directory.entryList(nameFilter);
367 for (
auto &indexName : indexList)
369 if (fileCountMatches(directory, indexName))
372 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
374 indexCheckBox->
setStyleSheet(
"QCheckBox{font-weight: bold; color:green}");
380int OpsAstrometryIndexFiles::indexFileCount(
QString indexName)
395bool OpsAstrometryIndexFiles::fileCountMatches(
QDir directory,
QString indexName)
397 QString indexNameMatch = indexName.
left(10) +
"*.fits";
399 return list.
count() == indexFileCount(indexName);
402void OpsAstrometryIndexFiles::slotOpenIndexFileDirectory()
404 if(indexLocations->count() == 0)
410bool OpsAstrometryIndexFiles::astrometryIndicesAreAvailable()
412 auto url =
QUrl(indexURL->text());
415 timeout.setInterval(5000);
416 timeout.setSingleShot(
true);
418 while (!response->isFinished())
420 if (!timeout.isActive())
422 response->deleteLater();
425 qApp->processEvents();
430 response->deleteLater();
432 return wasSuccessful;
435void OpsAstrometryIndexFiles::downloadIndexFile(
const QString &URL,
const QString &fileN,
const QString &indexSeriesName,
436 int currentIndex,
int maxIndex,
double fileSize)
439 downloadTime.
start();
442 if (currentIndex < 10)
443 indexString =
'0' + indexString;
445 QString uiIndexName = indexSeriesName;
447 uiIndexName = uiIndexName.
left(10);
449 QProgressBar *indexDownloadProgress = findChild<QProgressBar *>(uiIndexName +
"_progress");
450 QLabel *indexDownloadInfo = findChild<QLabel *>(uiIndexName +
"_info");
451 QPushButton *indexDownloadCancel = findChild<QPushButton *>(uiIndexName +
"_cancel");
452 QLabel *indexDownloadPerc = findChild<QLabel *>(uiIndexName +
"_perc");
454 setDownloadInfoVisible(indexSeriesName,
true);
456 if(indexDownloadInfo)
458 if (indexDownloadProgress && maxIndex > 0)
459 indexDownloadProgress->
setValue(currentIndex * 100 / maxIndex);
461 indexDownloadInfo->
setText(info);
462 emit newDownloadProgress(info);
467 indexURL.
replace(
'*', indexString);
476 if(fileSize > 4000000)
477 timeout = fileSize / downloadSpeed;
484 if(indexDownloadPerc)
487 [ = ](qint64 bytesReceived, qint64 bytesTotal)
489 if (indexDownloadProgress)
491 indexDownloadProgress->
setValue(bytesReceived);
492 indexDownloadProgress->
setMaximum(bytesTotal);
495 indexDownloadPerc->
setText(info);
496 emit newDownloadProgress(info);
501 timeoutTimer.disconnect();
504 KSNotification::error(
505 i18n(
"Download Timed out. Either the network is not fast enough, the file is not accessible, or you are not connected."),
507 disconnectDownload(cancelConnection, replyConnection, percentConnection);
513 setDownloadInfoVisible(indexSeriesName,
false);
515 timeoutTimer.start(timeout);
520 qDebug() << Q_FUNC_INFO <<
"Download Cancelled.";
522 disconnectDownload(cancelConnection, replyConnection, percentConnection);
523 emit newDownloadProgress(
i18n(
"%1 download cancelled.", indexSeriesName));
529 setDownloadInfoVisible(indexSeriesName,
false);
538 disconnectDownload(cancelConnection, replyConnection, percentConnection);
539 setDownloadInfoVisible(indexSeriesName,
false);
551 indexFileN.
replace(
'*', indexString);
553 QFile file(indexFileN);
558 KSNotification::error(
i18n(
"File Write Error"),
i18n(
"Error"), 10);
564 file.write(responseData.
data(), responseData.
size());
567 int dtime = downloadTime.
elapsed();
568 actualdownloadSpeed = (actualdownloadSpeed + (downloadedFileSize / dtime)) / 2;
569 qDebug() << Q_FUNC_INFO <<
"Filesize: " << downloadedFileSize <<
", time: " << dtime <<
", inst speed: " <<
570 downloadedFileSize / dtime <<
571 ", averaged speed: " << actualdownloadSpeed;
572 emit newDownloadProgress(
i18n(
"%1 download complete.", indexSeriesName));
578 KSNotification::error(
i18n(
"Astrometry Folder Permissions Error"),
i18n(
"Error"), 10);
581 if (currentIndex == maxIndex)
586 downloadIndexFile(URL, fileN, indexSeriesName, currentIndex + 1, maxIndex, fileSize);
591void OpsAstrometryIndexFiles::setDownloadInfoVisible(
const QString &indexSeriesName,
bool set)
593 QString uiIndexName = indexSeriesName;
595 uiIndexName = uiIndexName.
left(10);
597 QProgressBar *indexDownloadProgress = findChild<QProgressBar *>(uiIndexName +
"_progress");
598 QLabel *indexDownloadInfo = findChild<QLabel *>(uiIndexName +
"_info");
599 QPushButton *indexDownloadCancel = findChild<QPushButton *>(uiIndexName +
"_cancel");
600 QLabel *indexDownloadPerc = findChild<QLabel *>(uiIndexName +
"_perc");
601 if (indexDownloadProgress)
603 if (indexDownloadInfo)
605 if (indexDownloadCancel)
607 if (indexDownloadPerc)
614 disconnect(*cancelConnection);
616 disconnect(*replyConnection);
617 if(percentConnection)
618 disconnect(*percentConnection);
621void OpsAstrometryIndexFiles::downloadOrDeleteIndexFiles(
bool checked)
625 if (indexLocations->count() == 0)
628 QString astrometryDataDir = indexLocations->currentText();
631 if (indexLocations->currentIndex() == 0 && indexLocations->count() > 1)
633 astrometryDataDir = findFirstWritableDir();
634 if (astrometryDataDir.
isEmpty())
636 KSNotification::sorry(
i18n(
"No writable index file directory found."),
i18n(
"Error"), 10);
642 KSNotification::sorry(
643 i18n(
"The selected Index File directory does not exist. Please either create it or choose another."),
i18n(
"Sorry"), 10);
649 QString indexSeriesName = checkBox->
text().remove(
'&');
650 QString filePath = astrometryDataDir +
'/' + indexSeriesName;
651 QString fileNumString = indexSeriesName.
mid(8, 2);
658 nullptr,
i18n(
"The file %1 already exists in another directory. Are you sure you want to download it to this directory as well?",
668 if (astrometryIndicesAreAvailable())
673 if (this->indexURL->text().
endsWith(
"/"))
675 BASE_URL = this->indexURL->text();
679 BASE_URL = this->indexURL->text() +
"/";
683 URL = BASE_URL +
"4100/" + indexSeriesName;
684 else if (indexSeriesName.startsWith(
QLatin1String(
"index-42")))
685 URL = BASE_URL +
"4200/" + indexSeriesName;
686 else if (indexSeriesName.startsWith(
QLatin1String(
"index-52")))
687 URL =
"https://portal.nersc.gov/project/cosmo/temp/dstn/index-5200/LITE/" + indexSeriesName;
689 int maxIndex = indexFileCount(indexSeriesName) - 1;
691 double fileSize = 1E11 * qPow(astrometryIndex.key(fileNumString),
694 fileSize /= maxIndex;
695 downloadIndexFile(URL, filePath, indexSeriesName, 0, maxIndex, fileSize);
699 KSNotification::sorry(
i18n(
"Could not contact Astrometry Index Server."),
i18n(
"Error"), 10);
705 nullptr,
i18n(
"Are you sure you want to delete these index files? %1", indexSeriesName),
709 if (
QFileInfo(astrometryDataDir).isWritable())
712 QDir directory(astrometryDataDir);
714 for (
auto &fileName : indexList)
716 if (fileName.contains(indexSeriesName.left(10)))
718 if (!directory.
remove(fileName))
720 KSNotification::error(
i18n(
"File Delete Error"),
i18n(
"Error"), 10);
730 KSNotification::error(
i18n(
"Astrometry Folder Permissions Error"),
i18n(
"Error"), 10);
738QString OpsAstrometryIndexFiles::findFirstWritableDir()
740 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
741 if (astrometryDataDirs.
isEmpty())
745 if (astrometryDataDirs.
count() > 1)
749 for (
const QString &dir : astrometryDataDirs)
752 if (dirInfo.exists() && dirInfo.isWritable())
Align class handles plate-solving and polar alignment measurement and correction using astrometry....
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
QString path(const QString &relativePath)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString label(StandardShortcut id)
qsizetype size() const const
void currentIndexChanged(int index)
bool openUrl(const QUrl &url)
QStringList entryList(Filters filters, SortFlags sort) const const
bool remove(const QString &fileName)
qint64 elapsed() const const
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, Options options)
bool exists(const QString &path)
bool isWritable() const const
qint64 size() const const
QString errorString() const const
void setText(const QString &)
void append(QList< T > &&value)
qsizetype count() const const
bool isEmpty() const const
bool removeOne(const AT &t)
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
NetworkError error() const const
QObject * sender() const const
void setMaximum(int maximum)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)