From ae84cbdfe0f1756dd903e8d83e76e7e0eef673ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Fri, 12 Apr 2024 09:58:21 +0200 Subject: [PATCH] Add modifing FITS records --- scriptengine.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++ scriptengine.h | 18 ++++++ 2 files changed, 167 insertions(+) diff --git a/scriptengine.cpp b/scriptengine.cpp index dc32057..6d61640 100644 --- a/scriptengine.cpp +++ b/scriptengine.cpp @@ -5,6 +5,7 @@ #include "loadrunable.h" #include "rawimage.h" #include "loadrunable.h" +#include namespace Script { @@ -16,6 +17,8 @@ ScriptEngine::ScriptEngine(QObject *parent) : QObject(parent) { QJSValue engine = _jsEngine->newQObject(this); _jsEngine->globalObject().setProperty("engine", engine); + QJSValue fitsRecordObject = _jsEngine->newQMetaObject(&FITSRecordModify::staticMetaObject); + _jsEngine->globalObject().setProperty("FITSRecordModify", fitsRecordObject); _database->init(QLatin1String("scriptengine")); _semaphore.release(_pool->maxThreadCount()); } @@ -303,6 +306,136 @@ QJSValue File::fitsRecords() return array; } +bool File::modifyFITSRecords(const FITSRecordModify *modify) +{ + _fitsKeywordsLoaded = false; + _fitsKeywords.clear(); + + if(QRegularExpression("fits", QRegularExpression::CaseInsensitiveOption).match(suffix()).hasMatch()) + { + fitsfile *file; + int status = 0; + fits_open_diskfile(&file, _path.toLocal8Bit().data(), READWRITE, &status); + int num = 0; + fits_get_num_hdus(file, &num, &status); + if(status) + { + _engine->newMessage("Failed to open FITS file", true); + return false; + } + int imgtype; + int naxis; + long naxes[3] = {0}; + int type = -1; + for(int i=1; i <= num; i++) + { + fits_movabs_hdu(file, i, IMAGE_HDU, &status); + fits_get_hdu_type(file, &type, &status); + fits_get_img_param(file, 3, &imgtype, &naxis, naxes, &status); + if(type == IMAGE_HDU && naxis >= 2 && naxis <= 3 && status == 0) + break; + if(i == num)return false; + } + + for(auto &remove : modify->_remove) + { + fits_delete_key(file, remove.toLatin1().data(), &status); + } + for(auto &record : modify->_update) + { + switch(record.value.typeId()) + { + case QMetaType::Bool: + { + int val = record.value.toBool(); + fits_update_key(file, TLOGICAL, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::Int: + case QMetaType::UInt: + { + long long val = record.value.toLongLong(); + fits_update_key(file, TLONGLONG, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::QString: + { + QByteArray val = record.value.toString().toLatin1(); + fits_update_key(file, TSTRING, record.key.data(), val.isEmpty() ? nullptr : val.data(), record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::Float: + case QMetaType::Double: + { + double val = record.value.toDouble(); + fits_update_key(file, TDOUBLE, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + default: + _engine->newMessage("Unknown type for KEY " + record.key, true); + return false; + break; + } + if(status) + { + char error[100]; + fits_get_errstatus(status, error); + _engine->newMessage(QString("Error when updating KEY {} {}").arg(record.key).arg(error), true); + return false; + } + } + + for(auto &record : modify->_add) + { + switch(record.value.typeId()) + { + case QMetaType::Bool: + { + int val = record.value.toBool(); + fits_write_key(file, TLOGICAL, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::Int: + case QMetaType::UInt: + { + long long val = record.value.toLongLong(); + fits_write_key(file, TLONGLONG, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::QString: + { + QByteArray val = record.value.toString().toLatin1(); + fits_write_key(file, TSTRING, record.key.data(), val.isEmpty() ? nullptr : val.data(), record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + case QMetaType::Float: + case QMetaType::Double: + { + double val = record.value.toDouble(); + fits_write_key(file, TDOUBLE, record.key.data(), &val, record.comment.isEmpty() ? nullptr : record.comment.data(), &status); + break; + } + default: + _engine->newMessage("Unknown type for KEY " + record.key, true); + return false; + break; + } + if(status) + { + char error[100]; + fits_get_errstatus(status, error); + _engine->newMessage(QString("Error when adding KEY {} {}").arg(record.key).arg(error), true); + return false; + } + } + fits_close_file(file, &status); + + return status == 0; + } + + return false; +} + bool File::isMarked() const { return _engine->isMarked(this); @@ -408,4 +541,20 @@ void ScriptEngineThread::interrupt() if(_engine)_engine->interrupt(); } +void FITSRecordModify::removeKeyword(const QString &key) +{ + if(!_remove.contains(key)) + _remove.append(key); +} + +void FITSRecordModify::updateKeyword(const QString &key, const QVariant &value, const QString &comment) +{ + _update.append({key.toLatin1(), value, comment.toLatin1()}); +} + +void FITSRecordModify::addKeyword(const QString &key, const QVariant &value, const QString &comment) +{ + _update.append({key.toLatin1(), value, comment.toLatin1()}); +} + } diff --git a/scriptengine.h b/scriptengine.h index 83abc4c..f6b6fca 100644 --- a/scriptengine.h +++ b/scriptengine.h @@ -64,6 +64,8 @@ signals: void finished(); }; +class FITSRecordModify; + class File : public QObject { Q_OBJECT @@ -93,6 +95,7 @@ public: Q_INVOKABLE QString fitsValue(const QString &key); Q_INVOKABLE QJSValue fitsValues(const QString &key); Q_INVOKABLE QJSValue fitsRecords(); + Q_INVOKABLE bool modifyFITSRecords(const FITSRecordModify *modify); Q_INVOKABLE bool isMarked() const; Q_INVOKABLE File* copy(const QString &newpath) const; Q_INVOKABLE bool move(const QString &newpath); @@ -101,6 +104,21 @@ public: Q_INVOKABLE QJSValue stats(); }; +class FITSRecordModify : public QObject +{ + Q_OBJECT + QStringList _remove; + QVector _update; + QVector _add; + + friend class File; +public: + Q_INVOKABLE FITSRecordModify(){}; + Q_INVOKABLE void removeKeyword(const QString &key); + Q_INVOKABLE void updateKeyword(const QString &key, const QVariant &value, const QString &comment = QString()); + Q_INVOKABLE void addKeyword(const QString &key, const QVariant &value, const QString &comment = QString()); +}; + } #endif // SCRIPTENGINE_H