Kstars

opsastrometryindexfiles.cpp
1
2#include "opsastrometryindexfiles.h"
3
4#include "align.h"
5#include "kstars.h"
6#include "ksutils.h"
7#include "Options.h"
8#include "ksnotification.h"
9
10#include <KConfigDialog>
11#include <KMessageBox>
12#include <QFileDialog>
13#include <QDesktopServices>
14
15namespace Ekos
16{
17OpsAstrometryIndexFiles::OpsAstrometryIndexFiles(Align *parent) : QDialog(KStars::Instance())
18{
19 setupUi(this);
20
21 downloadSpeed = 100;
22 actualdownloadSpeed = downloadSpeed;
23 alignModule = parent;
24 manager = new QNetworkAccessManager();
25
26 indexURL->setText("http://data.astrometry.net/");
27
28 //Get a pointer to the KConfigDialog
29 // m_ConfigDialog = KConfigDialog::exists( "alignsetFtings" );
30 connect(openIndexFileDirectory, SIGNAL(clicked()), this, SLOT(slotOpenIndexFileDirectory()));
31
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";
52
53 QList<QCheckBox *> checkboxes = findChildren<QCheckBox *>();
54
55 connect(indexLocations, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
56 &OpsAstrometryIndexFiles::slotUpdate);
57
58 for (auto &checkBox : checkboxes)
59 {
60 connect(checkBox, &QCheckBox::clicked, this, &OpsAstrometryIndexFiles::downloadOrDeleteIndexFiles);
61 }
62
63 QList<QProgressBar *> progressBars = findChildren<QProgressBar *>();
64 QList<QLabel *> qLabels = findChildren<QLabel *>();
65 QList<QPushButton *> qButtons = findChildren<QPushButton *>();
66
67 for (auto &bar : progressBars)
68 {
69 if(bar->objectName().contains("progress"))
70 {
71 bar->setVisible(false);
72 bar->setTextVisible(false);
73 }
74 }
75
76 for (auto &button : qButtons)
77 {
78 if(button->objectName().contains("cancel"))
79 {
80 button->setVisible(false);
81 }
82 }
83
84 for (QLabel * label : qLabels)
85 {
86 if(label->text().contains("info") || label->text().contains("perc"))
87 {
88 label->setVisible(false);
89 }
90 }
91
92 connect(addIndexFileDirectory, &QAbstractButton::clicked, this, [this]()
93 {
94 QString dir = QFileDialog::getExistingDirectory(this, "Load Index File Directory",
98 if (dir.isEmpty())
99 return;
100 addDirectoryToList(dir);
101 });
102 connect(removeIndexFileDirectory, &QAbstractButton::clicked, this, [this]()
103 {
104 if(indexLocations->currentIndex() != 0)
105 removeDirectoryFromList(indexLocations->currentText());
106 });
107
108
109}
110
111void OpsAstrometryIndexFiles::showEvent(QShowEvent *)
112{
113 updateIndexDirectoryList();
114
115}
116
117void OpsAstrometryIndexFiles::updateIndexDirectoryList()
118{
119 // This is needed because they might have directories stored in the config file.
120 // So we can't just use the options folder list.
121 QStringList astrometryDataDirs = KSUtils::getAstrometryDataDirs();
122
123 indexLocations->clear();
124 if(astrometryDataDirs.count() > 1)
125 indexLocations->addItem("All Sources");
126 indexLocations->addItems(astrometryDataDirs);
127 slotUpdate();
128}
129
130void OpsAstrometryIndexFiles::addDirectoryToList(QString directory)
131{
132 QDir dir(directory);
133 if(!dir.exists())
134 return;
135 QString directoryPath = dir.absolutePath();
136
137 QStringList indexFileDirs = Options::astrometryIndexFolderList();
138 if(indexFileDirs.contains(directoryPath))
139 return;
140 indexFileDirs.append(directoryPath);
141 Options::setAstrometryIndexFolderList(indexFileDirs);
142 updateIndexDirectoryList();
143}
144
145void OpsAstrometryIndexFiles::removeDirectoryFromList(QString directory)
146{
147 QStringList indexFileDirs = Options::astrometryIndexFolderList();
148 if(indexFileDirs.contains(directory))
149 {
150 indexFileDirs.removeOne(directory);
151 Options::setAstrometryIndexFolderList(indexFileDirs);
152 updateIndexDirectoryList();
153 }
154}
155
156void OpsAstrometryIndexFiles::downloadSingleIndexFile(const QString &indexFileName)
157{
158 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
159 if (astrometryDataDirs.isEmpty())
160 {
161 KSNotification::sorry(i18n("No index file directories configured."), i18n("Error"), 10);
162 return;
163 }
164
165 // Skip first directory if it's "All Sources"
166 if (astrometryDataDirs.count() > 1)
167 astrometryDataDirs.removeFirst();
168
169 // Check if file exists in any directory
170 for (const QString &dir : astrometryDataDirs)
171 {
172 QDir directory(dir);
173 if (directory.exists())
174 {
175 if (fileCountMatches(directory, indexFileName))
176 {
177 return;
178 }
179 }
180 }
181
182 QString astrometryDataDir = findFirstWritableDir();
183 if (astrometryDataDir.isEmpty())
184 {
185 KSNotification::sorry(i18n("No writable index file directory found."), i18n("Error"), 10);
186 return;
187 }
188
189 if (!astrometryIndicesAreAvailable())
190 {
191 KSNotification::sorry(i18n("Could not contact Astrometry Index Server."), i18n("Error"), 10);
192 return;
193 }
194
195 QString BASE_URL;
196 if (indexURL->text().endsWith("/"))
197 BASE_URL = indexURL->text();
198 else
199 BASE_URL = indexURL->text() + "/";
200
201 QString URL;
202 if (indexFileName.startsWith(QLatin1String("index-41")))
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;
208 else
209 return;
210
211 QString filePath = astrometryDataDir + '/' + indexFileName;
212 QString fileNumString = indexFileName.mid(8, 2);
213
214 // Find the checkbox for this index series
215 QString indexName = indexFileName;
216 indexName.replace('-', '_');
217 indexName = indexName.left(10);
218 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
219 if (!indexCheckBox)
220 return;
221
222 double fileSize = 1E11 * qPow(astrometryIndex.key(fileNumString), -1.909);
223 downloadIndexFile(URL, filePath, indexFileName, 0, 0, fileSize);
224
225 // Update UI after download completes
226 slotUpdate();
227}
228
229void OpsAstrometryIndexFiles::slotUpdate()
230{
231 QList<QCheckBox *> checkboxes = findChildren<QCheckBox *>();
232
233 for (auto &checkBox : checkboxes)
234 {
235 checkBox->setChecked(false);
236 }
237
238 if(indexLocations->count() == 0)
239 return;
240
241 double fov_w, fov_h, fov_pixscale;
242
243 // Values in arcmins. Scale in arcsec per pixel
244 alignModule->getFOVScale(fov_w, fov_h, fov_pixscale);
245
246 double fov_check = qMax(fov_w, fov_h);
247
248 FOVOut->setText(QString("%1' x %2'").arg(QString::number(fov_w, 'f', 2), QString::number(fov_h, 'f', 2)));
249
250 QStringList nameFilter("*.fits");
251
252 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
253
254 bool allDirsSelected = (indexLocations->currentIndex() == 0 && astrometryDataDirs.count() > 1);
255 bool folderIsWriteable;
256
257 QStringList astrometryDataDirsToIndex;
258
259 if(allDirsSelected)
260 {
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);
265 }
266 else
267 {
268 QString folderPath = indexLocations->currentText();
269 folderIsWriteable = QFileInfo(folderPath).isWritable();
270 if(folderIsWriteable)
271 folderDetails->setText(i18n("Downloads Enabled, the directory exists and is writeable."));
272 else
273 folderDetails->setText(i18n("Downloads Disabled, directory permissions issue."));
274 if(!QFileInfo::exists(folderPath))
275 folderDetails->setText(i18n("Downloads Disabled, directory does not exist."));
276 astrometryDataDirsToIndex << folderPath;
277 openIndexFileDirectory->setEnabled(true);
278 }
279 folderDetails->setCursorPosition(0);
280
281 //This loop checks all the folders that are supposed to be checked for the files
282 //It checks the box if it finds them
283 for(auto &astrometryDataDir : astrometryDataDirsToIndex)
284 {
285 QDir directory(astrometryDataDir);
286 QStringList indexList = directory.entryList(nameFilter);
287
288 for (auto &indexName : indexList)
289 {
290 if (fileCountMatches(directory, indexName))
291 {
292 indexName = indexName.replace('-', '_').left(10);
293 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
294 if (indexCheckBox)
295 indexCheckBox->setChecked(true);
296 }
297 }
298 }
299
300 for (auto &checkBox : checkboxes)
301 {
302 checkBox->setEnabled(folderIsWriteable);
303 checkBox->setIcon(QIcon(":/icons/astrometry-optional.svg"));
304 checkBox->setToolTip(i18n("Optional"));
305 checkBox->setStyleSheet("");
306 }
307
308 float last_skymarksize = 2;
309
310 for (auto &skymarksize : astrometryIndex.keys())
311 {
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))
320 {
321 if (indexCheckBox1)
322 {
323 indexCheckBox1->setIcon(QIcon(":/icons/astrometry-required.svg"));
324 indexCheckBox1->setToolTip(i18n("Required"));
325 }
326 if (indexCheckBox2)
327 {
328 indexCheckBox2->setIcon(QIcon(":/icons/astrometry-required.svg"));
329 indexCheckBox2->setToolTip(i18n("Required"));
330 }
331 if (indexCheckBox3)
332 {
333 indexCheckBox3->setIcon(QIcon(":/icons/astrometry-required.svg"));
334 indexCheckBox3->setToolTip(i18n("Required"));
335 }
336 }
337 else if (skymarksize >= 0.10 * fov_check && skymarksize <= fov_check)
338 {
339 if (indexCheckBox1)
340 {
341 indexCheckBox1->setIcon(QIcon(":/icons/astrometry-recommended.svg"));
342 indexCheckBox1->setToolTip(i18n("Recommended"));
343 }
344 if (indexCheckBox2)
345 {
346 indexCheckBox2->setIcon(QIcon(":/icons/astrometry-recommended.svg"));
347 indexCheckBox2->setToolTip(i18n("Recommended"));
348 }
349 if (indexCheckBox3)
350 {
351 indexCheckBox3->setIcon(QIcon(":/icons/astrometry-recommended.svg"));
352 indexCheckBox3->setToolTip(i18n("Recommended"));
353 }
354 }
355
356 last_skymarksize = skymarksize;
357 }
358
359 //This loop goes over all the directories and adds a stylesheet to change the look of the checkbox text
360 //if the File is installed in any directory. Note that this indicator is then used below in the
361 //Index File download function to check if they really want to do install a file that is installed.
362 for(QString astrometryDataDir : astrometryDataDirs)
363 {
364 QDir directory(astrometryDataDir);
365 QStringList indexList = directory.entryList(nameFilter);
366
367 for (auto &indexName : indexList)
368 {
369 if (fileCountMatches(directory, indexName))
370 {
371 indexName = indexName.replace('-', '_').left(10);
372 QCheckBox *indexCheckBox = findChild<QCheckBox *>(indexName);
373 if (indexCheckBox)
374 indexCheckBox->setStyleSheet("QCheckBox{font-weight: bold; color:green}");
375 }
376 }
377 }
378}
379
380int OpsAstrometryIndexFiles::indexFileCount(QString indexName)
381{
382 int count = 0;
383 if(indexName.contains("4207") || indexName.contains("4206") || indexName.contains("4205"))
384 count = 12;
385 else if(indexName.contains("4204") || indexName.contains("4203") || indexName.contains("4202")
386 || indexName.contains("4201") || indexName.contains("4200") || indexName.contains("5206")
387 || indexName.contains("5205") || indexName.contains("5204") || indexName.contains("5203")
388 || indexName.contains("5202") || indexName.contains("5201") || indexName.contains("5200"))
389 count = 48;
390 else
391 count = 1;
392 return count;
393}
394
395bool OpsAstrometryIndexFiles::fileCountMatches(QDir directory, QString indexName)
396{
397 QString indexNameMatch = indexName.left(10) + "*.fits";
398 QStringList list = directory.entryList(QStringList(indexNameMatch));
399 return list.count() == indexFileCount(indexName);
400}
401
402void OpsAstrometryIndexFiles::slotOpenIndexFileDirectory()
403{
404 if(indexLocations->count() == 0)
405 return;
406 QUrl path = QUrl::fromLocalFile(indexLocations->currentText());
408}
409
410bool OpsAstrometryIndexFiles::astrometryIndicesAreAvailable()
411{
412 auto url = QUrl(indexURL->text());
413 auto response = manager->get(QNetworkRequest(QUrl(url.url(QUrl::RemovePath))));
414 QTimer timeout(this);
415 timeout.setInterval(5000);
416 timeout.setSingleShot(true);
417 timeout.start();
418 while (!response->isFinished())
419 {
420 if (!timeout.isActive())
421 {
422 response->deleteLater();
423 return false;
424 }
425 qApp->processEvents();
426 }
427
428 timeout.stop();
429 bool wasSuccessful = (response->error() == QNetworkReply::NoError);
430 response->deleteLater();
431
432 return wasSuccessful;
433}
434
435void OpsAstrometryIndexFiles::downloadIndexFile(const QString &URL, const QString &fileN, const QString &indexSeriesName,
436 int currentIndex, int maxIndex, double fileSize)
437{
438 QElapsedTimer downloadTime;
439 downloadTime.start();
440
441 QString indexString = QString::number(currentIndex);
442 if (currentIndex < 10)
443 indexString = '0' + indexString;
444
445 QString uiIndexName = indexSeriesName;
446 uiIndexName.replace('-', '_');
447 uiIndexName = uiIndexName.left(10);
448
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");
453
454 setDownloadInfoVisible(indexSeriesName, true);
455
456 if(indexDownloadInfo)
457 {
458 if (indexDownloadProgress && maxIndex > 0)
459 indexDownloadProgress->setValue(currentIndex * 100 / maxIndex);
460 QString info = "(" + QString::number(currentIndex) + '/' + QString::number(maxIndex + 1) + ") ";
461 indexDownloadInfo->setText(info);
462 emit newDownloadProgress(info);
463 }
464
465 QString indexURL = URL;
466
467 indexURL.replace('*', indexString);
468
469 QNetworkReply *response = manager->get(QNetworkRequest(QUrl(indexURL)));
470
471 //Shut it down after too much time elapses.
472 //If the filesize is less than 4 MB, it sets the timeout for 1 minute or 60000 ms.
473 //If it's larger, it assumes a bad download rate of 1 Mbps (100 bytes/ms)
474 //and the calculation estimates the time in milliseconds it would take to download.
475 int timeout = 60000;
476 if(fileSize > 4000000)
477 timeout = fileSize / downloadSpeed;
478 //qDebug()<<"Filesize: "<< fileSize << ", timeout: " << timeout;
479
480 QMetaObject::Connection *cancelConnection = new QMetaObject::Connection();
481 QMetaObject::Connection *replyConnection = new QMetaObject::Connection();
482 QMetaObject::Connection *percentConnection = new QMetaObject::Connection();
483
484 if(indexDownloadPerc)
485 {
486 *percentConnection = connect(response, &QNetworkReply::downloadProgress,
487 [ = ](qint64 bytesReceived, qint64 bytesTotal)
488 {
489 if (indexDownloadProgress)
490 {
491 indexDownloadProgress->setValue(bytesReceived);
492 indexDownloadProgress->setMaximum(bytesTotal);
493 }
494 QString info = QString::number(bytesReceived * 100 / bytesTotal) + '%';
495 indexDownloadPerc->setText(info);
496 emit newDownloadProgress(info);
497 });
498
499 }
500
501 timeoutTimer.disconnect();
502 connect(&timeoutTimer, &QTimer::timeout, this, [&]()
503 {
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."),
506 i18n("Error"), 10);
507 disconnectDownload(cancelConnection, replyConnection, percentConnection);
508 if(response)
509 {
510 response->abort();
511 response->deleteLater();
512 }
513 setDownloadInfoVisible(indexSeriesName, false);
514 });
515 timeoutTimer.start(timeout);
516
517 *cancelConnection = connect(indexDownloadCancel, &QPushButton::clicked,
518 [ = ]()
519 {
520 qDebug() << Q_FUNC_INFO << "Download Cancelled.";
521 timeoutTimer.stop();
522 disconnectDownload(cancelConnection, replyConnection, percentConnection);
523 emit newDownloadProgress(i18n("%1 download cancelled.", indexSeriesName));
524 if(response)
525 {
526 response->abort();
527 response->deleteLater();
528 }
529 setDownloadInfoVisible(indexSeriesName, false);
530 });
531
532 *replyConnection = connect(response, &QNetworkReply::finished, this,
533 [ = ]()
534 {
535 timeoutTimer.stop();
536 if(response)
537 {
538 disconnectDownload(cancelConnection, replyConnection, percentConnection);
539 setDownloadInfoVisible(indexSeriesName, false);
540 response->deleteLater();
541 if (response->error() != QNetworkReply::NoError)
542 {
543 emit newDownloadProgress(response->errorString());
544 KSNotification::error(response->errorString(), i18n("Error"), 10);
545 return;
546 }
547
548 QByteArray responseData = response->readAll();
549 QString indexFileN = fileN;
550
551 indexFileN.replace('*', indexString);
552
553 QFile file(indexFileN);
554 if (QFileInfo(QFileInfo(file).path()).isWritable())
555 {
556 if (!file.open(QIODevice::WriteOnly))
557 {
558 KSNotification::error(i18n("File Write Error"), i18n("Error"), 10);
559 slotUpdate();
560 return;
561 }
562 else
563 {
564 file.write(responseData.data(), responseData.size());
565 file.close();
566 int downloadedFileSize = QFileInfo(file).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));
573
574 }
575 }
576 else
577 {
578 KSNotification::error(i18n("Astrometry Folder Permissions Error"), i18n("Error"), 10);
579 }
580
581 if (currentIndex == maxIndex)
582 {
583 slotUpdate();
584 }
585 else
586 downloadIndexFile(URL, fileN, indexSeriesName, currentIndex + 1, maxIndex, fileSize);
587 }
588 });
589}
590
591void OpsAstrometryIndexFiles::setDownloadInfoVisible(const QString &indexSeriesName, bool set)
592{
593 QString uiIndexName = indexSeriesName;
594 uiIndexName.replace('-', '_');
595 uiIndexName = uiIndexName.left(10);
596
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)
602 indexDownloadProgress->setVisible(set);
603 if (indexDownloadInfo)
604 indexDownloadInfo->setVisible(set);
605 if (indexDownloadCancel)
606 indexDownloadCancel->setVisible(set);
607 if (indexDownloadPerc)
608 indexDownloadPerc->setVisible(set);
609}
610void OpsAstrometryIndexFiles::disconnectDownload(QMetaObject::Connection *cancelConnection,
611 QMetaObject::Connection *replyConnection, QMetaObject::Connection *percentConnection)
612{
613 if(cancelConnection)
614 disconnect(*cancelConnection);
615 if(replyConnection)
616 disconnect(*replyConnection);
617 if(percentConnection)
618 disconnect(*percentConnection);
619}
620
621void OpsAstrometryIndexFiles::downloadOrDeleteIndexFiles(bool checked)
622{
623 QCheckBox *checkBox = qobject_cast<QCheckBox *>(QObject::sender());
624
625 if (indexLocations->count() == 0)
626 return;
627
628 QString astrometryDataDir = indexLocations->currentText();
629
630 // If "All Sources" is selected, find first writable directory
631 if (indexLocations->currentIndex() == 0 && indexLocations->count() > 1)
632 {
633 astrometryDataDir = findFirstWritableDir();
634 if (astrometryDataDir.isEmpty())
635 {
636 KSNotification::sorry(i18n("No writable index file directory found."), i18n("Error"), 10);
637 return;
638 }
639 }
640 else if (!QFileInfo::exists(astrometryDataDir))
641 {
642 KSNotification::sorry(
643 i18n("The selected Index File directory does not exist. Please either create it or choose another."), i18n("Sorry"), 10);
644 return;
645 }
646
647 if (checkBox)
648 {
649 QString indexSeriesName = checkBox->text().remove('&');
650 QString filePath = astrometryDataDir + '/' + indexSeriesName;
651 QString fileNumString = indexSeriesName.mid(8, 2);
652
653 if (checked)
654 {
655 if(!checkBox->styleSheet().isEmpty()) //This means that the checkbox has a stylesheet so the index file was installed someplace.
656 {
658 nullptr, i18n("The file %1 already exists in another directory. Are you sure you want to download it to this directory as well?",
659 indexSeriesName),
660 i18n("Install File(s)"), KStandardGuiItem::cont(),
661 KStandardGuiItem::cancel(), "install_index_files_warning"))
662 {
663 slotUpdate();
664 return;
665 }
666 }
667 checkBox->setChecked(!checked);
668 if (astrometryIndicesAreAvailable())
669 {
670 QString BASE_URL;
671 QString URL;
672
673 if (this->indexURL->text().endsWith("/"))
674 {
675 BASE_URL = this->indexURL->text();
676 }
677 else
678 {
679 BASE_URL = this->indexURL->text() + "/";
680 }
681
682 if (indexSeriesName.startsWith(QLatin1String("index-41")))
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;
688
689 int maxIndex = indexFileCount(indexSeriesName) - 1;
690
691 double fileSize = 1E11 * qPow(astrometryIndex.key(fileNumString),
692 -1.909); //This estimates the file size based on skymark size obtained from the index number.
693 if(maxIndex != 0)
694 fileSize /= maxIndex; //FileSize is divided between multiple files for some index series.
695 downloadIndexFile(URL, filePath, indexSeriesName, 0, maxIndex, fileSize);
696 }
697 else
698 {
699 KSNotification::sorry(i18n("Could not contact Astrometry Index Server."), i18n("Error"), 10);
700 }
701 }
702 else
703 {
705 nullptr, i18n("Are you sure you want to delete these index files? %1", indexSeriesName),
706 i18n("Delete File(s)"), KStandardGuiItem::cont(),
707 KStandardGuiItem::cancel(), "delete_index_files_warning"))
708 {
709 if (QFileInfo(astrometryDataDir).isWritable())
710 {
711 QStringList nameFilter("*.fits");
712 QDir directory(astrometryDataDir);
713 QStringList indexList = directory.entryList(nameFilter);
714 for (auto &fileName : indexList)
715 {
716 if (fileName.contains(indexSeriesName.left(10)))
717 {
718 if (!directory.remove(fileName))
719 {
720 KSNotification::error(i18n("File Delete Error"), i18n("Error"), 10);
721 slotUpdate();
722 return;
723 }
724 slotUpdate();
725 }
726 }
727 }
728 else
729 {
730 KSNotification::error(i18n("Astrometry Folder Permissions Error"), i18n("Error"), 10);
731 slotUpdate();
732 }
733 }
734 }
735 }
736}
737
738QString OpsAstrometryIndexFiles::findFirstWritableDir()
739{
740 QStringList astrometryDataDirs = Options::astrometryIndexFolderList();
741 if (astrometryDataDirs.isEmpty())
742 return QString();
743
744 // Skip first directory if it's "All Sources"
745 if (astrometryDataDirs.count() > 1)
746 astrometryDataDirs.removeFirst();
747
748 // Find first writable directory
749 for (const QString &dir : astrometryDataDirs)
750 {
751 QFileInfo dirInfo(dir);
752 if (dirInfo.exists() && dirInfo.isWritable())
753 return dir;
754 }
755
756 return QString();
757}
758}
Align class handles plate-solving and polar alignment measurement and correction using astrometry....
Definition align.h:77
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
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)
KGuiItem cont()
KGuiItem cancel()
QString label(StandardShortcut id)
void setChecked(bool)
void clicked(bool checked)
void setIcon(const QIcon &icon)
char * data()
qsizetype size() const const
void currentIndexChanged(int index)
bool openUrl(const QUrl &url)
QStringList entryList(Filters filters, SortFlags sort) const const
QString homePath()
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
QByteArray readAll()
void setText(const QString &)
void append(QList< T > &&value)
qsizetype count() const const
bool isEmpty() const const
void removeFirst()
bool removeOne(const AT &t)
virtual void abort()=0
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
NetworkError error() const const
void deleteLater()
QObject * sender() const const
void setMaximum(int maximum)
void setValue(int value)
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)
void timeout()
QUrl fromLocalFile(const QString &localFile)
void setStyleSheet(const QString &styleSheet)
void setToolTip(const QString &)
virtual void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 28 2025 11:55:58 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.