diff --git a/kstars/auxiliary/ksutils.h b/kstars/auxiliary/ksutils.h --- a/kstars/auxiliary/ksutils.h +++ b/kstars/auxiliary/ksutils.h @@ -255,12 +255,19 @@ #ifdef Q_OS_OSX void copyResourcesFolderFromAppBundle(QString folder); bool copyDataFolderFromAppBundleIfNeeded(); //The boolean returns true if the data folders are good to go. -bool getAstrometryDataDir(QString &dataDir); -bool setAstrometryDataDir(QString dataDir); bool configureAstrometry(); +bool replaceIndexFileNotYetSet(); bool copyRecursively(QString sourceFolder, QString destFolder); #endif +bool configureLocalAstrometryConfIfNecessary(); +bool createLocalAstrometryConf(); +QString getAstrometryConfFilePath(); +QStringList getAstrometryDataDirs(); +bool addAstrometryDataDir(QString dataDir); +bool removeAstrometryDataDir(QString dataDir); + + struct JPLFilter { QByteArray item; diff --git a/kstars/auxiliary/ksutils.cpp b/kstars/auxiliary/ksutils.cpp --- a/kstars/auxiliary/ksutils.cpp +++ b/kstars/auxiliary/ksutils.cpp @@ -18,6 +18,7 @@ #include "ksutils.h" #include "config-kstars.h" #include "ksnotification.h" +#include "ekos_align_debug.h" #include "deepskyobject.h" #ifndef KSTARS_LITE @@ -1220,23 +1221,230 @@ return true; //This means the data directory was good to go from the start and the wizard did not run. } -bool getAstrometryDataDir(QString &dataDir) + +//Can this and the linux method be merged somehow? See KSUtils::createLocalAstrometryConf +bool configureAstrometry() +{ + QStringList astrometryDataDirs = getAstrometryDataDirs(); + if (astrometryDataDirs.count() == 0) + return false; + QString defaultAstrometryDataDir = getDefaultPath("AstrometryIndexFileLocation"); + if(astrometryDataDirs.contains("IndexFileLocationNotYetSet")) + replaceIndexFileNotYetSet(); + if (QDir(defaultAstrometryDataDir).exists() == false) + { + if (KMessageBox::warningYesNo( + nullptr, i18n("The selected Astrometry Index File Location:\n %1 \n does not exist. Do you want to make the directory?", defaultAstrometryDataDir), + i18n("Make Astrometry Index File Directory?")) == KMessageBox::Yes) + { + if(QDir(defaultAstrometryDataDir).mkdir(defaultAstrometryDataDir)) + { + KSNotification::info(i18n("The Default Astrometry Index File Location was created.")); + } + else + { + KSNotification::sorry(i18n("The Default Astrometry Index File Directory does not exist and was not able to be created.")); + } + } + else + { + return false; + } + } + + return true; +} + +bool replaceIndexFileNotYetSet() +{ + QString confPath = KSUtils::getAstrometryConfFilePath(); + + QFile confFile(confPath); + QString contents; + if (confFile.open(QIODevice::ReadOnly) == false) + { + KSNotification::error( i18n("Astrometry Configuration File Read Error.")); + return false; + } + else + { + QByteArray fileContent = confFile.readAll(); + confFile.close(); + QString contents = QString::fromLatin1(fileContent); + contents.replace("IndexFileLocationNotYetSet",getDefaultPath("AstrometryIndexFileLocation")); + + if (confFile.open(QIODevice::WriteOnly) == false) + { + KSNotification::error( i18n("Internal Astrometry Configuration File Write Error.")); + return false; + } + else + { + QTextStream out(&confFile); + out << contents; + confFile.close(); + } + } + return true; +} + +bool copyRecursively(QString sourceFolder, QString destFolder) +{ + QDir sourceDir(sourceFolder); + + if (!sourceDir.exists()) + return false; + + QDir destDir(destFolder); + if (!destDir.exists()) + destDir.mkdir(destFolder); + + QStringList files = sourceDir.entryList(QDir::Files); + for (int i = 0; i < files.count(); i++) + { + QString srcName = sourceFolder + QDir::separator() + files[i]; + QString destName = destFolder + QDir::separator() + files[i]; + QFile::copy(srcName, destName); //Note this does not overwrite files + } + + files.clear(); + files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (int i = 0; i < files.count(); i++) + { + QString srcName = sourceFolder + QDir::separator() + files[i]; + QString destName = destFolder + QDir::separator() + files[i]; + copyRecursively(srcName, destName); + } + + return true; +} +#endif + +//Note maybe the Mac and Linux versions of creating the local astrometry conf file and index file folder can be merged. +//I moved both of them here and this method references each one separately. +//One is createLocalAstrometryConf and the other is configureAstrometry +bool configureLocalAstrometryConfIfNecessary() +{ +#ifdef Q_OS_LINUX + QString confPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); + if (QFileInfo(confPath).exists() == false) + { + if(createLocalAstrometryConf() == false) + return false; + } + +#else //Mac + if(configureAstrometry() == false) + { + KMessageBox::information( + nullptr, + i18n( + "Failed to properly configure astrometry config file. Please click the options button in the lower right of the Astrometry Tab in Ekos to correct your settings. Then try starting Ekos again."), + i18n("Astrometry Config File Error"), "astrometry_configuration_failure_warning"); + return false; + } +#endif + return true; +} + +//Can this and the mac method be merged somehow? See KSUtils::configureAstrometry. +bool createLocalAstrometryConf() { - QString confPath; + bool rc = false; + QString confPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); + QString systemConfPath = "/etc/astrometry.cfg"; + + // Check if directory already exists, if it doesn't create one + QDir writableDir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); + if (writableDir.exists() == false) + { + rc = writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); + + if (rc == false) + { + qCCritical(KSTARS_EKOS_ALIGN) << "Failed to create local astrometry directory"; + return false; + } + } + + // Now copy system astrometry.cfg to local directory + rc = QFile(systemConfPath).copy(confPath); + + if (rc == false) + { + qCCritical(KSTARS_EKOS_ALIGN) << "Failed to copy" << systemConfPath << "to" << confPath; + return false; + } + + QFile localConf(confPath); + + // Open file and add our own path to it + if (localConf.open(QFile::ReadWrite)) + { + QString all = localConf.readAll(); + QStringList lines = all.split("\n"); + for (int i = 0; i < lines.count(); i++) + { + if (lines[i].startsWith("add_path")) + { + lines.insert(i + 1, QString("add_path %1astrometry").arg(KSPaths::writableLocation(QStandardPaths::GenericDataLocation))); + break; + } + } + + // Clear contents + localConf.resize(0); + + // Now write back all the lines including our own inserted above + QTextStream out(&localConf); + for(const QString &line : lines) + out << line << endl; + localConf.close(); + return true; + } + + qCCritical(KSTARS_EKOS_ALIGN) << "Failed to open local astrometry config" << confPath; + return false; +} + +QString getAstrometryConfFilePath() +{ if (Options::astrometryConfFileIsInternal()) - confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; + #ifdef Q_OS_LINUX + return KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); + #else //Mac + return QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; + #endif else - confPath = Options::astrometryConfFile(); + return Options::astrometryConfFile(); +} + +QStringList getAstrometryDataDirs() +{ + QStringList dataDirs; + QString confPath = KSUtils::getAstrometryConfFilePath(); QFile confFile(confPath); if (confFile.open(QIODevice::ReadOnly) == false) { - KSNotification::error(i18n("Astrometry configuration file corrupted or missing: %1\nPlease set the " - "configuration file full path in INDI options.", - Options::astrometryConfFile())); - return false; + bool confFileExists = false; + if(Options::astrometryConfFileIsInternal()) + { + if(KSUtils::configureLocalAstrometryConfIfNecessary()) + { + if (confFile.open(QIODevice::ReadOnly)) + confFileExists = true; + } + } + if(!confFileExists) + { + KSNotification::error(i18n("Astrometry configuration file corrupted or missing: %1\nPlease set the " + "configuration file full path in INDI options.", + confPath)); + return dataDirs; + } } QTextStream in(&confFile); @@ -1250,24 +1458,23 @@ line = line.trimmed(); if (line.startsWith(QLatin1String("add_path"))) { - dataDir = line.trimmed().mid(9).trimmed(); - return true; + dataDirs << line.mid(9).trimmed(); } } + // if(dataDirs.size()==0) + // KSNotification::error(i18n("Unable to find data dir in astrometry configuration file.")); - KSNotification::error(i18n("Unable to find data dir in astrometry configuration file.")); - return false; + return dataDirs; } -bool setAstrometryDataDir(QString dataDir) +bool addAstrometryDataDir(QString dataDir) { - if(Options::astrometryIndexFileLocation() != dataDir) - Options::setAstrometryIndexFileLocation(dataDir); - QString confPath; - if (Options::astrometryConfFileIsInternal()) - confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; - else - confPath = Options::astrometryConfFile(); + //This will need to be fixed! + //if(Options::astrometryIndexFileLocation() != dataDir) + // Options::setAstrometryIndexFileLocation(dataDir); + + QString confPath = KSUtils::getAstrometryConfFilePath(); + QStringList astrometryDataDirs = getAstrometryDataDirs(); QFile confFile(confPath); QString contents; @@ -1280,130 +1487,95 @@ { QTextStream in(&confFile); QString line; - bool foundPathBefore = false; - bool fileNeedsUpdating = false; + bool foundSpot = false; while (!in.atEnd()) { line = in.readLine(); + if (line.trimmed().startsWith(QLatin1String("add_path"))) { - if (!foundPathBefore) //This will ensure there is not more than one add_path line in the file. + if (!foundSpot) { - foundPathBefore = true; - QString dataDirInFile = line.trimmed().mid(9).trimmed(); - if (dataDirInFile != dataDir) //Update to the correct path. - { - contents += "add_path " + dataDir + '\n'; - fileNeedsUpdating = true; - } + foundSpot = true; + for(QString astrometryDataDir:astrometryDataDirs) + contents += "add_path " + astrometryDataDir + '\n'; + contents += "add_path " + dataDir + '\n'; + } + else + { + //Do not keep adding the other add_paths because they just got added in the seciton above. } } else { contents += line + '\n'; } } + if(!foundSpot) + { + for(QString astrometryDataDir:astrometryDataDirs) + contents += "add_path " + astrometryDataDir + '\n'; + contents += "add_path " + dataDir + '\n'; + } + confFile.close(); - if (fileNeedsUpdating) + + if (confFile.open(QIODevice::WriteOnly) == false) { - if (confFile.open(QIODevice::WriteOnly) == false) - { - KSNotification::error( i18n("Internal Astrometry Configuration File Write Error.")); - return false; - } - else - { - QTextStream out(&confFile); - out << contents; - confFile.close(); - } + KSNotification::error( i18n("Internal Astrometry Configuration File Write Error.")); + return false; + } + else + { + QTextStream out(&confFile); + out << contents; + confFile.close(); } } return true; } -bool configureAstrometry() +bool removeAstrometryDataDir(QString dataDir) { - QString astrometryDataDir; - if (KSUtils::getAstrometryDataDir(astrometryDataDir) == false) - return false; - if(astrometryDataDir == "IndexFileLocationNotYetSet") + QString confPath = KSUtils::getAstrometryConfFilePath(); + QStringList astrometryDataDirs = getAstrometryDataDirs(); + + QFile confFile(confPath); + QString contents; + if (confFile.open(QIODevice::ReadOnly) == false) { - astrometryDataDir = Options::astrometryIndexFileLocation(); - setAstrometryDataDir(astrometryDataDir); + KSNotification::error( i18n("Astrometry Configuration File Read Error.")); + return false; } - if(Options::astrometryIndexFileLocation() != astrometryDataDir) + else { - if (KMessageBox::warningYesNo( - nullptr, i18n("The Astrometry Index File Location Stored in KStars: \n %1 \n does not match the Index file location in the config file: \n %2 \n Do you want to update the config file?", Options::astrometryIndexFileLocation(), astrometryDataDir), - i18n("Update Config File?")) == KMessageBox::Yes) + QTextStream in(&confFile); + QString line; + while (!in.atEnd()) { - astrometryDataDir = Options::astrometryIndexFileLocation(); - setAstrometryDataDir(astrometryDataDir); + line = in.readLine(); + if (line.mid(9).trimmed() != dataDir) + { + contents += line + '\n'; + } + } - else + confFile.close(); + + if (confFile.open(QIODevice::WriteOnly) == false) { + KSNotification::error( i18n("Internal Astrometry Configuration File Write Error.")); return false; } - } - if (QDir(astrometryDataDir).exists() == false) - { - if (KMessageBox::warningYesNo( - nullptr, i18n("The selected Astrometry Index File Location:\n %1 \n does not exist. Do you want to make the directory?", astrometryDataDir), - i18n("Make Astrometry Index File Directory?")) == KMessageBox::Yes) - { - if(QDir(astrometryDataDir).mkdir(astrometryDataDir)) - { - KSNotification::info(i18n("The Astrometry Index File Location was created.")); - } - else - { - KSNotification::sorry(i18n("The Astrometry Index File Directory does not exist and was not able to be created.")); - } - } else { - - return false; + QTextStream out(&confFile); + out << contents; + confFile.close(); } } - - //If the Index File Directories match and the directory exists, we are good to go. return true; } - -bool copyRecursively(QString sourceFolder, QString destFolder) -{ - QDir sourceDir(sourceFolder); - - if (!sourceDir.exists()) - return false; - - QDir destDir(destFolder); - if (!destDir.exists()) - destDir.mkdir(destFolder); - - QStringList files = sourceDir.entryList(QDir::Files); - for (int i = 0; i < files.count(); i++) - { - QString srcName = sourceFolder + QDir::separator() + files[i]; - QString destName = destFolder + QDir::separator() + files[i]; - QFile::copy(srcName, destName); //Note this does not overwrite files - } - - files.clear(); - files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - for (int i = 0; i < files.count(); i++) - { - QString srcName = sourceFolder + QDir::separator() + files[i]; - QString destName = destFolder + QDir::separator() + files[i]; - copyRecursively(srcName, destName); - } - - return true; -} -#endif - QByteArray getJPLQueryString(const QByteArray &kind, const QByteArray &dataFields, const QVector &filters) { QByteArray query("obj_group=all&obj_kind=" + kind + "&obj_numbered=all&OBJ_field=0&ORB_field=0"); diff --git a/kstars/ekos/align/align.cpp b/kstars/ekos/align/align.cpp --- a/kstars/ekos/align/align.cpp +++ b/kstars/ekos/align/align.cpp @@ -218,11 +218,9 @@ page = dialog->addPage(opsAstrometry, i18n("Solver Options")); page->setIcon(QIcon::fromTheme("configure")); -#ifdef Q_OS_OSX opsAstrometryCfg = new OpsAstrometryCfg(this); page = dialog->addPage(opsAstrometryCfg, i18n("Astrometry.cfg")); page->setIcon(QIcon::fromTheme("document-edit")); -#endif #ifndef Q_OS_WIN opsAstrometryIndexFiles = new OpsAstrometryIndexFiles(this); diff --git a/kstars/ekos/align/offlineastrometryparser.h b/kstars/ekos/align/offlineastrometryparser.h --- a/kstars/ekos/align/offlineastrometryparser.h +++ b/kstars/ekos/align/offlineastrometryparser.h @@ -48,8 +48,6 @@ private: bool astrometryNetOK(); - bool createLocalAstrometryConf(); - bool getAstrometryDataDir(QString &dataDir); QMap astrometryIndex; QString parity; diff --git a/kstars/ekos/align/offlineastrometryparser.cpp b/kstars/ekos/align/offlineastrometryparser.cpp --- a/kstars/ekos/align/offlineastrometryparser.cpp +++ b/kstars/ekos/align/offlineastrometryparser.cpp @@ -51,20 +51,6 @@ bool OfflineAstrometryParser::init() { -#ifdef Q_OS_OSX - if (Options::astrometryConfFileIsInternal()) - { - if(KSUtils::configureAstrometry() == false) - { - KMessageBox::information( - nullptr, - i18n( - "Failed to properly configure astrometry config file. Please click the options button in the lower right of the Astrometry Tab in Ekos to correct your settings. Then try starting Ekos again."), - i18n("Astrometry Config File Error"), "astrometry_configuration_failure_warning"); - return false; - } - } -#endif if (astrometryFilesOK) return true; @@ -123,22 +109,21 @@ { bool solverOK = false, wcsinfoOK = false; + QFileInfo solverFileInfo; + if (Options::astrometrySolverIsInternal()) { - QFileInfo solverFileInfo(QCoreApplication::applicationDirPath() + "/astrometry/bin/solve-field"); - solverOK = solverFileInfo.exists() && solverFileInfo.isFile(); + KSUtils::configureLocalAstrometryConfIfNecessary(); + #ifdef Q_OS_LINUX + solverFileInfo = QFileInfo(Options::astrometrySolverBinary()); + #else //Mac + solverFileInfo = QFileInfo(QCoreApplication::applicationDirPath() + "/astrometry/bin/solve-field"); + #endif } else - { - QFileInfo solverFileInfo(Options::astrometrySolverBinary()); - solverOK = solverFileInfo.exists() && solverFileInfo.isFile(); + solverFileInfo = QFileInfo(Options::astrometrySolverBinary()); -#ifdef Q_OS_LINUX - QString confPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); - if (QFileInfo(confPath).exists() == false) - createLocalAstrometryConf(); -#endif - } + solverOK = solverFileInfo.exists() && solverFileInfo.isFile(); if (Options::astrometryWCSIsInternal()) { @@ -166,31 +151,24 @@ double fov_lower = 0.10 * fov_x; double fov_upper = fov_x; QStringList indexFiles; - QString astrometryDataDir; + QStringList astrometryDataDirs; bool indexesOK = true; -#ifdef Q_OS_OSX - if (KSUtils::getAstrometryDataDir(astrometryDataDir) == false) - return; -#else - getAstrometryDataDir(astrometryDataDir); -#endif + astrometryDataDirs = KSUtils::getAstrometryDataDirs(); QStringList nameFilter("*.fits"); - QDir directory(astrometryDataDir); - QStringList indexList = directory.entryList(nameFilter); - - // JM 2018-09-26: Also add locally stored indexes. -#ifdef Q_OS_LINUX - QDir localAstrometry(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); - indexList << localAstrometry.entryList(nameFilter); -#endif + QStringList indexList; + for(QString astrometryDataDir:astrometryDataDirs) + { + QDir directory(astrometryDataDir); + indexList << directory.entryList(nameFilter); + } QString indexSearch = indexList.join(" "); QString startIndex, lastIndex; unsigned int missingIndexes = 0; - foreach (float skymarksize, astrometryIndex.keys()) + for (float skymarksize: astrometryIndex.keys()) { if (skymarksize >= fov_lower && skymarksize <= fov_upper) { @@ -225,45 +203,6 @@ } } -bool OfflineAstrometryParser::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) - { - KSNotification::error(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; - } - } - - KSNotification::error(i18n("Unable to find data dir in astrometry configuration file.")); - return false; -} - bool OfflineAstrometryParser::startSovler(const QString &filename, const QStringList &args, bool generated) { INDI_UNUSED(generated); @@ -275,18 +214,7 @@ (args.contains("-3") || args.contains("-L"))) solverArgs << "--parity" << parity; - QString confPath; - if (Options::astrometryConfFileIsInternal()) - confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; - else - { - // JM 2018-09-26: On Linux, load the local config file. -#ifdef Q_OS_LINUX - confPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); -#else - confPath = Options::astrometryConfFile(); -#endif - } + QString confPath = KSUtils::getAstrometryConfFilePath(); solverArgs << "--config" << confPath; QString solutionFile = QDir::tempPath() + "/solution.wcs"; @@ -452,63 +380,4 @@ align->appendLogText(solver->readAll().trimmed()); } -bool OfflineAstrometryParser::createLocalAstrometryConf() -{ - bool rc = false; - - QString confPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + QLatin1Literal("/astrometry.cfg"); - QString systemConfPath = Options::astrometryConfFile(); - - // Check if directory already exists, if it doesn't create one - QDir writableDir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); - if (writableDir.exists() == false) - { - rc = writableDir.mkdir(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); - - if (rc == false) - { - qCCritical(KSTARS_EKOS_ALIGN) << "Failed to create local astrometry directory"; - return false; - } - } - - // Now copy system astrometry.cfg to local directory - rc = QFile(systemConfPath).copy(confPath); - - if (rc == false) - { - qCCritical(KSTARS_EKOS_ALIGN) << "Failed to copy" << systemConfPath << "to" << confPath; - return false; - } - - QFile localConf(confPath); - - // Open file and add our own path to it - if (localConf.open(QFile::ReadWrite)) - { - QString all = localConf.readAll(); - QStringList lines = all.split("\n"); - for (int i = 0; i < lines.count(); i++) - { - if (lines[i].startsWith("add_path")) - { - lines.insert(i + 1, QString("add_path %1astrometry").arg(KSPaths::writableLocation(QStandardPaths::GenericDataLocation))); - break; - } - } - - // Clear contents - localConf.resize(0); - - // Now write back all the lines including our own inserted above - QTextStream out(&localConf); - for(const QString &line : lines) - out << line << endl; - localConf.close(); - return true; - } - - qCCritical(KSTARS_EKOS_ALIGN) << "Failed to open local astrometry config" << confPath; - return false; -} } diff --git a/kstars/ekos/align/opsalign.cpp b/kstars/ekos/align/opsalign.cpp --- a/kstars/ekos/align/opsalign.cpp +++ b/kstars/ekos/align/opsalign.cpp @@ -34,17 +34,18 @@ connect(m_ConfigDialog->button(QDialogButtonBox::Ok), SIGNAL(clicked()), SLOT(slotApply())); connect(SetupPython, SIGNAL(clicked()), this, SLOT(setupPython())); -#ifdef Q_OS_OSX - connect(kcfg_AstrometrySolverIsInternal, SIGNAL(clicked()), this, SLOT(toggleSolverInternal())); - kcfg_AstrometrySolverIsInternal->setToolTip(i18n("Internal or External Plate Solver?")); - if (Options::astrometrySolverIsInternal()) - kcfg_AstrometrySolverBinary->setEnabled(false); connect(kcfg_AstrometryConfFileIsInternal, SIGNAL(clicked()), this, SLOT(toggleConfigInternal())); kcfg_AstrometryConfFileIsInternal->setToolTip(i18n("Internal or External astrometry.cfg?")); if (Options::astrometryConfFileIsInternal()) kcfg_AstrometryConfFile->setEnabled(false); +#ifdef Q_OS_OSX + connect(kcfg_AstrometrySolverIsInternal, SIGNAL(clicked()), this, SLOT(toggleSolverInternal())); + kcfg_AstrometrySolverIsInternal->setToolTip(i18n("Internal or External Plate Solver?")); + if (Options::astrometrySolverIsInternal()) + kcfg_AstrometrySolverBinary->setEnabled(false); + connect(kcfg_AstrometryWCSIsInternal, SIGNAL(clicked()), this, SLOT(toggleWCSInternal())); kcfg_AstrometryWCSIsInternal->setToolTip(i18n("Internal or External wcsinfo?")); if (Options::astrometryWCSIsInternal()) @@ -56,7 +57,6 @@ #else kcfg_AstrometrySolverIsInternal->setVisible(false); - kcfg_AstrometryConfFileIsInternal->setVisible(false); kcfg_AstrometryWCSIsInternal->setVisible(false); kcfg_UseDefaultPython->setVisible(false); diff --git a/kstars/ekos/align/opsastrometrycfg.h b/kstars/ekos/align/opsastrometrycfg.h --- a/kstars/ekos/align/opsastrometrycfg.h +++ b/kstars/ekos/align/opsastrometrycfg.h @@ -19,9 +19,14 @@ explicit OpsAstrometryCfg(Align *parent); virtual ~OpsAstrometryCfg() override = default; + protected: + void showEvent(QShowEvent *) override; + private slots: void slotLoadCFG(); - void slotSetAstrometryIndexFileLocation(); + void slotAddAstrometryIndexFileLocation(); + void slotRemoveAstrometryIndexFileLocation(); + void slotClickAstrometryIndexFileLocation(QListWidgetItem *item); void slotApply(); void slotCFGEditorUpdated(); diff --git a/kstars/ekos/align/opsastrometrycfg.cpp b/kstars/ekos/align/opsastrometrycfg.cpp --- a/kstars/ekos/align/opsastrometrycfg.cpp +++ b/kstars/ekos/align/opsastrometrycfg.cpp @@ -7,9 +7,11 @@ #include "Options.h" #include "ksnotification.h" #include "ui_opsastrometrycfg.h" +#include "kspaths.h" #include #include +#include namespace Ekos { @@ -27,30 +29,45 @@ connect(astrometryCFGDisplay, SIGNAL(textChanged()), SLOT(slotCFGEditorUpdated())); connect(loadCFG, SIGNAL(clicked()), this, SLOT(slotLoadCFG())); - connect(setIndexFileB, SIGNAL(clicked()), this, SLOT(slotSetAstrometryIndexFileLocation())); + connect(addIndexFilePath, SIGNAL(clicked()), this, SLOT(slotAddAstrometryIndexFileLocation())); + connect(removeIndexFilePath, SIGNAL(clicked()), this, SLOT(slotRemoveAstrometryIndexFileLocation())); + + connect(AstrometryIndexFileLocations, &QListWidget::itemDoubleClicked, this, &OpsAstrometryCfg::slotClickAstrometryIndexFileLocation); slotLoadCFG(); } -void OpsAstrometryCfg::slotLoadCFG() +void OpsAstrometryCfg::showEvent(QShowEvent *) { - QString confPath; + slotLoadCFG(); +} - if (Options::astrometryConfFileIsInternal()) - confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; - else - confPath = Options::astrometryConfFile(); +void OpsAstrometryCfg::slotLoadCFG() +{ + QString confPath = KSUtils::getAstrometryConfFilePath(); QFile confFile(confPath); astrometryCFGLocation->setText(confPath); if (confFile.open(QIODevice::ReadOnly) == false) { - KSNotification::error(i18n("Astrometry configuration file corrupted or missing: %1\nPlease set the " - "configuration file full path in INDI options.", - Options::astrometryConfFile())); - return; + bool confFileExists = false; + if(Options::astrometryConfFileIsInternal()) + { + if(KSUtils::configureLocalAstrometryConfIfNecessary()) + { + if (confFile.open(QIODevice::ReadOnly)) + confFileExists = true; + } + } + if(!confFileExists) + { + KSNotification::error(i18n("Astrometry configuration file corrupted or missing: %1\nPlease set the " + "configuration file full path in INDI options.", + confPath)); + return; + } } QTextStream in(&confFile); @@ -60,26 +77,52 @@ astrometryCFGDisplay->setPlainText(currentCFGText); confFile.close(); + AstrometryIndexFileLocations->clear(); + QStringList astrometryDataDirs = KSUtils::getAstrometryDataDirs(); + for(QString astrometryDataDir:astrometryDataDirs) + { + QListWidgetItem *item = new QListWidgetItem(astrometryDataDir); + item->setIcon(QIcon::fromTheme("stock_folder")); + AstrometryIndexFileLocations->addItem(item); + } } -void OpsAstrometryCfg::slotSetAstrometryIndexFileLocation() +void OpsAstrometryCfg::slotAddAstrometryIndexFileLocation() { -#ifdef Q_OS_OSX - KSUtils::setAstrometryDataDir(kcfg_AstrometryIndexFileLocation->text()); -#endif + QString dir = + QFileDialog::getExistingDirectory(KStars::Instance(), i18n("Index File Directory"), QDir::homePath()); + + if (dir.isEmpty()) + return; + + KSUtils::addAstrometryDataDir(dir); + slotLoadCFG(); +} + +void OpsAstrometryCfg::slotRemoveAstrometryIndexFileLocation() +{ + if(AstrometryIndexFileLocations->selectedItems().count() == 0) + { + KSNotification::error(i18n("Please select an Index Path to remove first.")); + return; + } + KSUtils::removeAstrometryDataDir(AstrometryIndexFileLocations->selectedItems().first()->text()); slotLoadCFG(); } +void OpsAstrometryCfg::slotClickAstrometryIndexFileLocation(QListWidgetItem *item) +{ + if(AstrometryIndexFileLocations->count()==0) + return; + QUrl path = QUrl::fromLocalFile(item->text()); + QDesktopServices::openUrl(path); +} + void OpsAstrometryCfg::slotApply() { if (currentCFGText != astrometryCFGDisplay->toPlainText()) { - QString confPath; - - if (Options::astrometryConfFileIsInternal()) - confPath = QCoreApplication::applicationDirPath() + "/astrometry/bin/astrometry.cfg"; - else - confPath = Options::astrometryConfFile(); + QString confPath = KSUtils::getAstrometryConfFilePath(); QFile confFile(confPath); if (confFile.open(QIODevice::WriteOnly) == false) @@ -91,12 +134,8 @@ confFile.close(); KSNotification::info(i18n("Astrometry.cfg successfully saved.")); currentCFGText = astrometryCFGDisplay->toPlainText(); - QString astrometryDataDir; -#ifdef Q_OS_OSX - KSUtils::getAstrometryDataDir(astrometryDataDir); -#endif - if(astrometryDataDir != kcfg_AstrometryIndexFileLocation->text()) - kcfg_AstrometryIndexFileLocation->setText(astrometryDataDir); + AstrometryIndexFileLocations->clear(); + AstrometryIndexFileLocations->addItems(KSUtils::getAstrometryDataDirs()); } } } diff --git a/kstars/ekos/align/opsastrometrycfg.ui b/kstars/ekos/align/opsastrometrycfg.ui --- a/kstars/ekos/align/opsastrometrycfg.ui +++ b/kstars/ekos/align/opsastrometrycfg.ui @@ -6,7 +6,7 @@ 0 0 - 400 + 407 300 @@ -59,30 +59,55 @@ <html><head/><body><p>This is the absolute location of the Astrometry.cfg file on the filesystem.</p></body></html> - Index File Location: + Index File Locations: - - - true + + + + 16777215 + 70 + - - false + + + + + + + 32 + 32 + - - <html><head/><body><p>This is the absolute location of the Astrometry.cfg file on the filesystem.</p></body></html> + + + 32 + 32 + + + + + - - - <html><head/><body><p>This button will let you reload the Astrometry.cfg file in the event that something was changed outside of KStars.</p></body></html> + + + + 32 + 32 + + + + + 32 + 32 + - Set + - diff --git a/kstars/ekos/align/opsastrometryindexfiles.h b/kstars/ekos/align/opsastrometryindexfiles.h --- a/kstars/ekos/align/opsastrometryindexfiles.h +++ b/kstars/ekos/align/opsastrometryindexfiles.h @@ -35,7 +35,6 @@ void downloadOrDeleteIndexFiles(bool checked); private: - bool getAstrometryDataDir(QString &dataDir); void downloadIndexFile(const QString &URL, const QString &fileN, QCheckBox *checkBox, int currentIndex, int maxIndex, double fileSize); bool astrometryIndicesAreAvailable(); diff --git a/kstars/ekos/align/opsastrometryindexfiles.cpp b/kstars/ekos/align/opsastrometryindexfiles.cpp --- a/kstars/ekos/align/opsastrometryindexfiles.cpp +++ b/kstars/ekos/align/opsastrometryindexfiles.cpp @@ -3,6 +3,7 @@ #include "align.h" #include "kstars.h" +#include "ksutils.h" #include "Options.h" #include "kspaths.h" #include "ksnotification.h" @@ -48,9 +49,11 @@ QList checkboxes = findChildren(); + connect(indexLocations,static_cast(&QComboBox::currentIndexChanged), this, &OpsAstrometryIndexFiles::slotUpdate); + for (auto &checkBox : checkboxes) { - connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(downloadOrDeleteIndexFiles(bool))); + connect(checkBox, &QCheckBox::clicked, this,&OpsAstrometryIndexFiles::downloadOrDeleteIndexFiles); } QList progressBars = findChildren(); @@ -85,11 +88,29 @@ void OpsAstrometryIndexFiles::showEvent(QShowEvent *) { + QStringList astrometryDataDirs =KSUtils::getAstrometryDataDirs(); + + if (astrometryDataDirs.count() == 0) + return; + indexLocations->clear(); + if(astrometryDataDirs.count()>1) + indexLocations->addItem("All Sources"); + indexLocations->addItems(astrometryDataDirs); slotUpdate(); } void OpsAstrometryIndexFiles::slotUpdate() { + QList checkboxes = findChildren(); + + for (auto &checkBox : checkboxes) + { + checkBox->setChecked(false); + } + + if(indexLocations->count()==0) + return; + double fov_w, fov_h, fov_pixscale; // Values in arcmins. Scale in arcsec per pixel @@ -99,45 +120,67 @@ FOVOut->setText(QString("%1' x %2'").arg(QString::number(fov_w, 'f', 2), QString::number(fov_h, 'f', 2))); - QString astrometryDataDir; + QStringList nameFilter("*.fits"); - if (getAstrometryDataDir(astrometryDataDir) == false) - return; + if (Options::astrometrySolverIsInternal()) + KSUtils::configureLocalAstrometryConfIfNecessary(); - indexLocation->setText(astrometryDataDir); + QStringList astrometryDataDirs = KSUtils::getAstrometryDataDirs();; - QStringList nameFilter("*.fits"); - QDir directory(astrometryDataDir); - QStringList indexList = directory.entryList(nameFilter); + bool allDirsSelected = (indexLocations->currentIndex() == 0 && astrometryDataDirs.count() > 1); + bool folderIsWriteable; - // JM 2018-09-26: Also add locally stored indexes. -#ifdef Q_OS_LINUX - QDir localAstrometry(KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry")); - indexList << localAstrometry.entryList(nameFilter); -#endif + QStringList astrometryDataDirsToIndex; - for (auto &indexName : indexList) + if(allDirsSelected) { -#ifdef Q_OS_LINUX - if (fileCountMatches(directory, indexName) || fileCountMatches(localAstrometry, indexName)) -#else - if (fileCountMatches(directory, indexName)) -#endif + folderDetails->setText(i18n("Downloads Disabled, this is not a directory, it is a list of all index files.")); + folderIsWriteable = false; + astrometryDataDirsToIndex = astrometryDataDirs; + openIndexFileDirectory->setEnabled(false); + } + else + { + QString folderPath = indexLocations->currentText(); + folderIsWriteable = QFileInfo(folderPath).isWritable(); + if(folderIsWriteable) + folderDetails->setText(i18n("Downloads Enabled, the directory exists and is writeable.")); + else + folderDetails->setText(i18n("Downloads Disabled, directory permissions issue.")); + if(!QFileInfo(folderPath).exists()) + folderDetails->setText(i18n("Downloads Disabled, directory does not exist.")); + astrometryDataDirsToIndex << folderPath; + openIndexFileDirectory->setEnabled(true); + } + folderDetails->setCursorPosition(0); + + //This loop checks all the folders that are supposed to be checked for the files + //It checks the box if it finds them + for(QString astrometryDataDir:astrometryDataDirsToIndex) + { + QDir directory(astrometryDataDir); + QStringList indexList = directory.entryList(nameFilter); + for (auto &indexName : indexList) { - indexName = indexName.replace('-', '_').left(10); - QCheckBox *indexCheckBox = findChild(indexName); - if (indexCheckBox) - indexCheckBox->setChecked(true); + 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->setEnabled(folderIsWriteable); checkBox->setIcon(QIcon(":/icons/astrometry-optional.svg")); checkBox->setToolTip(i18n("Optional")); + checkBox->setStyleSheet(""); } float last_skymarksize = 2; @@ -182,6 +225,26 @@ last_skymarksize = skymarksize; } + + //This loop goes over all the directories and adds a stylesheet to change the look of the checkbox text + //if the File is installed in any directory. Note that this indicator is then used below in the + //Index File download function to check if they really want to do install a file that is installed. + for(QString astrometryDataDir:astrometryDataDirs) + { + 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->setStyleSheet("QCheckBox{font-weight: bold; color:green}"); + } + } + } } bool OpsAstrometryIndexFiles::fileCountMatches(QDir directory, QString indexName) @@ -200,52 +263,12 @@ void OpsAstrometryIndexFiles::slotOpenIndexFileDirectory() { - QString astrometryDataDir; - if (getAstrometryDataDir(astrometryDataDir) == false) + if(indexLocations->count()==0) return; - QUrl path = QUrl::fromLocalFile(astrometryDataDir); + QUrl path = QUrl::fromLocalFile(indexLocations->currentText()); 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) - { - KSNotification::error(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; - } - } - - KSNotification::error(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"))); @@ -421,7 +444,6 @@ indexDownloadCancel->setVisible(set); if (indexDownloadPerc) indexDownloadPerc->setVisible(set); - checkBox->setEnabled(!set); } void OpsAstrometryIndexFiles::disconnectDownload(QMetaObject::Connection *cancelConnection, QMetaObject::Connection *replyConnection, QMetaObject::Connection *percentConnection) { @@ -437,23 +459,35 @@ { QCheckBox *checkBox = qobject_cast(QObject::sender()); - QString astrometryDataDir; - if (getAstrometryDataDir(astrometryDataDir) == false) + if (indexLocations->count() == 0) return; + QString astrometryDataDir = indexLocations->currentText(); + if(!QFileInfo(astrometryDataDir).exists()) + { + KSNotification::sorry(i18n("The selected Index File directory does not exist. Please either create it or choose another.")); + } + if (checkBox) { QString indexSeriesName = checkBox->text().remove('&'); -#ifdef Q_OS_LINUX - QString filePath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Literal("astrometry") + '/' + indexSeriesName; -#else QString filePath = astrometryDataDir + '/' + indexSeriesName; -#endif QString fileNumString = indexSeriesName.mid(8, 2); int indexFileNum = fileNumString.toInt(); if (checked) { + if(checkBox->styleSheet() != "") //This means that the checkbox has a stylesheet so the index file was installed someplace. + { + if (KMessageBox::Cancel == KMessageBox::warningContinueCancel( + nullptr, i18n("The file %1 already exists in another directory. Are you sure you want to download it to this directory as well?", indexSeriesName), + i18n("Install File(s)"), KStandardGuiItem::cont(), + KStandardGuiItem::cancel(), "install_index_files_warning")) + { + slotUpdate(); + return; + } + } checkBox->setChecked(!checked); if (astrometryIndicesAreAvailable()) { @@ -486,8 +520,7 @@ i18n("Delete File(s)"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "delete_index_files_warning")) { - bool filesDeleted = false; - // Try to delete local files first + if (QFileInfo(astrometryDataDir).isWritable()) { QStringList nameFilter("*.fits"); QDir directory(astrometryDataDir); @@ -502,37 +535,14 @@ slotUpdate(); return; } - - filesDeleted = true; + slotUpdate(); } } } - - if (filesDeleted) + else { - 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)) - { - KSNotification::error(i18n("File Delete Error")); - slotUpdate(); - return; - } - } - } - } - else - { - KSNotification::error(i18n("Astrometry Folder Permissions Error")); - slotUpdate(); - } + KSNotification::error(i18n("Astrometry Folder Permissions Error")); + slotUpdate(); } } } diff --git a/kstars/ekos/align/opsastrometryindexfiles.ui b/kstars/ekos/align/opsastrometryindexfiles.ui --- a/kstars/ekos/align/opsastrometryindexfiles.ui +++ b/kstars/ekos/align/opsastrometryindexfiles.ui @@ -7,7 +7,7 @@ 0 0 768 - 852 + 888 @@ -188,66 +188,63 @@ - - + + - <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> - Index Files Location: + Open - - - 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 displays the current CCD field of view that will be used to calculate which index files are needed.</p></body></html> + + + Current CCD FOV: - - + + - <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> + <html><head/><body><p>This displays the path to the folder for the Astrometry Index Files on your computer.</p></body></html> - Open + Index Files Location: - + <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: + Folder Details: + + + + + + + false - + true - - - - Qt::Horizontal - - - - 40 - 20 - - - - diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg --- a/kstars/kstars.kcfg +++ b/kstars/kstars.kcfg @@ -1983,14 +1983,9 @@ Path to astrometry.net file location. KSUtils::getDefaultPath("AstrometryConfFile") - - - Astrometry.net Index files Location. - KSUtils::getDefaultPath("AstrometryIndexFileLocation") - - false + true