Scripting module

This commit is contained in:
2023-12-31 16:04:16 +01:00
parent faecb385aa
commit 11294bfcb0
9 changed files with 797 additions and 10 deletions
+10 -7
View File
@@ -17,7 +17,7 @@ if(SANITIZE_ADDRESS_LEAK)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak")
endif(SANITIZE_ADDRESS_LEAK) endif(SANITIZE_ADDRESS_LEAK)
find_package(Qt6 COMPONENTS Widgets Sql OpenGLWidgets REQUIRED) find_package(Qt6 COMPONENTS Widgets Sql OpenGLWidgets Qml REQUIRED)
find_library(GSL_LIB gsl REQUIRED) find_library(GSL_LIB gsl REQUIRED)
find_library(GSLCBLAS_LIB gslcblas REQUIRED) find_library(GSLCBLAS_LIB gslcblas REQUIRED)
find_library(EXIF_LIB exif REQUIRED) find_library(EXIF_LIB exif REQUIRED)
@@ -29,6 +29,7 @@ add_subdirectory(libXISF)
set(TENMON_SRC set(TENMON_SRC
about.cpp about.h about.cpp about.h
batchprocessing.cpp batchprocessing.h batchprocessing.ui
database.cpp database.h database.cpp database.h
databaseview.cpp databaseview.h databaseview.cpp databaseview.h
delete.cpp delete.cpp
@@ -44,6 +45,7 @@ set(TENMON_SRC
markedfiles.cpp markedfiles.h markedfiles.cpp markedfiles.h
rawimage.cpp rawimage.h rawimage.cpp rawimage.h
rawimage_sse.cpp rawimage_sse.cpp
scriptengine.cpp scriptengine.h
settingsdialog.cpp settingsdialog.h settingsdialog.cpp settingsdialog.h
starfit.cpp starfit.h starfit.cpp starfit.h
statusbar.cpp statusbar.h statusbar.cpp statusbar.h
@@ -67,11 +69,12 @@ elseif(APPLE)
set_source_files_properties(${tenmon_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_source_files_properties(${tenmon_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
else() else()
set(tenmon_ICON "") set(tenmon_ICON "")
find_package(Qt6 COMPONENTS DBus REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
pkg_search_module(GIO REQUIRED gio-2.0) pkg_search_module(GIO REQUIRED gio-2.0)
endif() endif()
add_executable(tenmon WIN32 MACOSX_BUNDLE ${tenmon_ICON} ${TENMON_SRC}) qt_add_executable(tenmon WIN32 MACOSX_BUNDLE ${tenmon_ICON} ${TENMON_SRC})
find_path(FITS_INCLUDE fitsio2.h PATH_SUFFIXES cfitsio REQUIRED) find_path(FITS_INCLUDE fitsio2.h PATH_SUFFIXES cfitsio REQUIRED)
target_include_directories(tenmon PRIVATE ${FITS_INCLUDE} ${CMAKE_BINARY_DIR} ${libXISF_SOURCE_DIR}) target_include_directories(tenmon PRIVATE ${FITS_INCLUDE} ${CMAKE_BINARY_DIR} ${libXISF_SOURCE_DIR})
@@ -80,16 +83,16 @@ if(UNIX AND NOT APPLE)
target_include_directories(tenmon PRIVATE ${GIO_INCLUDE_DIRS}) target_include_directories(tenmon PRIVATE ${GIO_INCLUDE_DIRS})
endif() endif()
target_link_libraries(tenmon Qt6::Widgets Qt6::Sql Qt6::OpenGLWidgets ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB} ${WCS_LIB} XISF) target_link_libraries(tenmon PRIVATE Qt6::Widgets Qt6::Sql Qt6::OpenGLWidgets Qt6::Qml ${GSL_LIB} ${GSLCBLAS_LIB} ${EXIF_LIB} ${FITS_LIB} ${RAW_LIB} ${WCS_LIB} XISF)
if(APPLE) if(APPLE)
target_link_libraries(tenmon "-framework CoreFoundation") target_link_libraries(tenmon PRIVATE "-framework CoreFoundation")
else() elseif(UNIX)
target_link_libraries(tenmon ${GIO_LDFLAGS}) target_link_libraries(tenmon PRIVATE Qt6::DBus ${GIO_LDFLAGS})
endif(APPLE) endif(APPLE)
if(LIBRAW_STATIC) if(LIBRAW_STATIC)
add_compile_definitions("LIBRAW_NODLL") add_compile_definitions("LIBRAW_NODLL")
target_link_libraries(tenmon jasper) target_link_libraries(tenmon PRIVATE jasper)
endif() endif()
install(TARGETS tenmon BUNDLE DESTINATION .) install(TARGETS tenmon BUNDLE DESTINATION .)
+208
View File
@@ -0,0 +1,208 @@
#include "batchprocessing.h"
#include "ui_batchprocessing.h"
#include <QDir>
#include <QFileDialog>
#include <QStandardPaths>
#include <QProcess>
#include <QSettings>
#include "scriptengine.h"
#ifdef Q_OS_LINUX
#include <QCloseEvent>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QMessageBox>
#endif
void scanDirectory(const QString &path, QStringList &files)
{
QFileInfo info(path);
if(info.isDir())
{
QDir dir(path);
QStringList entries = dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
for(QString &entry : entries)
scanDirectory(dir.absoluteFilePath(entry), files);
}
else if(info.isFile())
{
files.append(path);
}
}
QStringList scanDirectories(const QStringList &paths)
{
QStringList files;
for(const QString &path : paths)
scanDirectory(path, files);
return files;
}
void BatchProcessing::scanScriptDir()
{
_ui->scriptsList->clear();
QDir dir(_scriptBasePath);
for(const QString &script : dir.entryList(QDir::Files | QDir::Readable))
{
_ui->scriptsList->addItem(script);
}
}
BatchProcessing::BatchProcessing(QWidget *parent) : QDialog(parent)
{
_ui = new Ui::BatchProcessing;
_ui->setupUi(this);
QStringList scriptsPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
if(scriptsPath.size())
{
QDir dir(scriptsPath.first());
if(!dir.exists("scripts"))
{
if(!dir.mkpath("scripts"))
qWarning() << "Failed to create scripts directory";
}
dir.cd("scripts");
_scriptBasePath = dir.absolutePath() + "/";
scanScriptDir();
_fileWatcher.addPath(_scriptBasePath);
connect(&_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &BatchProcessing::scanScriptDir);
}
else
{
qWarning() << "Failed to get app data location";
}
connect(_ui->addFilesButton, &QPushButton::released, this, &BatchProcessing::addFiles);
connect(_ui->addDirButton, &QPushButton::released, this, &BatchProcessing::addDir);
connect(_ui->removeButton, &QPushButton::released, this, &BatchProcessing::removePath);
connect(_ui->removeAllButton, &QPushButton::released, this, &BatchProcessing::removeAllPaths);
connect(_ui->startButton, &QPushButton::released, this, &BatchProcessing::runScript);
connect(_ui->stopButton, &QPushButton::released, this, &BatchProcessing::stopScript);
connect(_ui->browseButton, &QPushButton::released, this, &BatchProcessing::browse);
connect(_ui->openScriptsButton, &QPushButton::released, this, &BatchProcessing::openScriptDir);
QSettings settings;
_ui->outputPath->setText(settings.value("batchprocessing/outputpath", QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).first()).toString());
}
BatchProcessing::~BatchProcessing()
{
delete _engineThread;
QSettings settings;
settings.setValue("batchprocessing/outputpath", _ui->outputPath->text());
delete _ui;
}
void BatchProcessing::closeEvent(QCloseEvent *event)
{
if(_engineThread)
{
QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Interrupt running script?"), tr("Interrupt running script?"));
if(ret == QMessageBox::StandardButton::Yes)
{
_engineThread->interrupt();
event->accept();
}
else
{
event->ignore();
}
}
else
{
event->accept();
}
}
void BatchProcessing::addFiles()
{
QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files"), "/home/nou/Obrázky/astro");
_ui->pathsList->addItems(files);
}
void BatchProcessing::addDir()
{
QString dir = QFileDialog::getExistingDirectory(this, tr("Select directory"), "/home/nou/Obrázky/astro");
if(!dir.isEmpty())
_ui->pathsList->addItem(dir);
}
void BatchProcessing::removePath()
{
for(auto &item : _ui->pathsList->selectedItems())
delete item;
}
void BatchProcessing::removeAllPaths()
{
_ui->pathsList->clear();
}
void BatchProcessing::browse()
{
QString output = QFileDialog::getExistingDirectory(this, tr("Select output directory"), "/home/nou/Obrázky");
if(!output.isEmpty())
_ui->outputPath->setText(output);
}
void BatchProcessing::openScriptDir()
{
#ifdef Q_OS_LINUX
QDBusConnection con = QDBusConnection::sessionBus();
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1", "ShowFolders");
QList<QVariant> args = {QStringList(QUrl::fromLocalFile(_scriptBasePath).toString()), QString()};
message.setArguments(args);
con.call(message);
#endif
#ifdef Q_OS_WINDOWS
QProcess::startDetached("explorer.exe", {QDir::toNativeSeparators(_scriptBasePath)});
#endif
}
void BatchProcessing::runScript()
{
_ui->log->clear();
auto selectedItems = _ui->scriptsList->selectedItems();
if(selectedItems.size())
{
_engineThread = new Script::ScriptEngineThread(this);
connect(_engineThread, &Script::ScriptEngineThread::newMessage, _ui->log, &QTextEdit::append);
connect(_engineThread, &Script::ScriptEngineThread::finished, this, &BatchProcessing::scriptFinished);
QStringList paths;
for(int i=0; i<_ui->pathsList->count(); i++)
paths.append(_ui->pathsList->item(i)->text());
QFileInfo outDir(_ui->outputPath->text());
if(outDir.exists() && outDir.isWritable())
{
_engineThread->setParams(_scriptBasePath + selectedItems.first()->text(), scanDirectories(paths), _ui->outputPath->text());
_engineThread->start();
_ui->startButton->setEnabled(false);
_ui->stopButton->setEnabled(true);
}
else
{
QMessageBox::warning(this, tr("Invalid output directory"), tr("Output directory path doesn't exist or is not writable"));
}
}
}
void BatchProcessing::stopScript()
{
qDebug() << "Stop script";
if(_engineThread)
_engineThread->interrupt();
}
void BatchProcessing::scriptFinished()
{
_ui->startButton->setEnabled(true);
_ui->stopButton->setEnabled(false);
qDebug() << "script finished";
delete _engineThread;
_engineThread = nullptr;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef BATCHPROCESSING_H
#define BATCHPROCESSING_H
#include <QDialog>
#include <QFileSystemWatcher>
#include "scriptengine.h"
namespace Ui { class BatchProcessing; }
class BatchProcessing : public QDialog
{
Ui::BatchProcessing *_ui;
QString _scriptBasePath;
QFileSystemWatcher _fileWatcher;
Script::ScriptEngineThread *_engineThread = nullptr;
private slots:
void scanScriptDir();
public:
explicit BatchProcessing(QWidget *parent = nullptr);
~BatchProcessing();
protected:
void closeEvent(QCloseEvent *event);
public slots:
void scriptDirChanged();
void addFiles();
void addDir();
void removePath();
void removeAllPaths();
void browse();
void openScriptDir();
void runScript();
void stopScript();
void scriptFinished();
};
#endif // BATCHPROCESSING_H
+226
View File
@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BatchProcessing</class>
<widget class="QDialog" name="BatchProcessing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<height>768</height>
</rect>
</property>
<property name="windowTitle">
<string>Batch Processing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Input files and directories</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="pathsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="addFilesButton">
<property name="text">
<string>Add files</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addDirButton">
<property name="text">
<string>Add directories</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeAllButton">
<property name="text">
<string>Remove all</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Output directory</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="outputPath">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Scripts</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="openScriptsButton">
<property name="text">
<string>Open scripts</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="scriptsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="log">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>FreeMono</family>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Start script</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Stop script</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>closeButton</sender>
<signal>released()</signal>
<receiver>BatchProcessing</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>973</x>
<y>745</y>
</hint>
<hint type="destinationlabel">
<x>511</x>
<y>383</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+2 -2
View File
@@ -10,12 +10,12 @@ Database::Database(QObject *parent) : QObject(parent)
{ {
} }
bool Database::init() bool Database::init(const QLatin1String &connectionName)
{ {
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir dir(path); QDir dir(path);
QSqlDatabase m_database = QSqlDatabase::addDatabase("QSQLITE"); QSqlDatabase m_database = QSqlDatabase::addDatabase("QSQLITE", connectionName);
if(!dir.mkpath(".")) if(!dir.mkpath("."))
return false; return false;
+1 -1
View File
@@ -24,7 +24,7 @@ class Database : public QObject
int m_progress; int m_progress;
public: public:
explicit Database(QObject *parent = 0); explicit Database(QObject *parent = 0);
bool init(); bool init(const QLatin1String &connectionName = QLatin1String(QSqlDatabase::defaultConnection));
bool mark(const QString &filename); bool mark(const QString &filename);
bool unmark(const QString &filename); bool unmark(const QString &filename);
bool mark(const QStringList &filenames); bool mark(const QStringList &filenames);
+6
View File
@@ -25,6 +25,7 @@
#include "statusbar.h" #include "statusbar.h"
#include "settingsdialog.h" #include "settingsdialog.h"
#include "histogram.h" #include "histogram.h"
#include "batchprocessing.h"
#ifdef __linux__ #ifdef __linux__
#include <sys/ioctl.h> #include <sys/ioctl.h>
@@ -151,6 +152,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
fileMenu->addAction(tr("Index directory"), this, SLOT(indexDir())); fileMenu->addAction(tr("Index directory"), this, SLOT(indexDir()));
fileMenu->addAction(tr("Reindex files"), this, SLOT(reindex())); fileMenu->addAction(tr("Reindex files"), this, SLOT(reindex()));
fileMenu->addAction(tr("Export database to CSV"), this, &MainWindow::exportCSV); fileMenu->addAction(tr("Export database to CSV"), this, &MainWindow::exportCSV);
fileMenu->addAction(tr("Batch processing"), [this](){
BatchProcessing *batchProcessing = new BatchProcessing(this);
batchProcessing->exec();
delete batchProcessing;
}, Qt::Key_B | Qt::CTRL);
fileMenu->addSeparator(); fileMenu->addSeparator();
QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, SLOT(liveMode(bool))); QAction *liveModeAction = fileMenu->addAction(tr("Live mode"), this, SLOT(liveMode(bool)));
liveModeAction->setCheckable(true); liveModeAction->setCheckable(true);
+224
View File
@@ -0,0 +1,224 @@
#include "scriptengine.h"
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#include "loadrunable.h"
namespace Script
{
ScriptEngine::ScriptEngine(QObject *parent) : QObject(parent)
, _jsEngine(new QJSEngine(this))
, _database(new Database(this))
{
QJSValue engine = _jsEngine->newQObject(this);
_jsEngine->globalObject().setProperty("engine", engine);
_database->init(QLatin1String("scriptengine"));
}
void ScriptEngine::setParams(const QString &scriptPath, const QStringList &paths, const QString &outputDir)
{
_scriptPath = scriptPath;
_paths = paths;
_outputDir = outputDir;
}
void ScriptEngine::reportError(const QString &message)
{
_jsEngine->throwError(message);
}
const QString &ScriptEngine::outputDir() const
{
return _outputDir;
}
void ScriptEngine::interrupt()
{
_jsEngine->setInterrupted(true);
}
void ScriptEngine::log(const QString &message)
{
emit newMessage(message);
}
void ScriptEngine::mark(File *file)
{
_database->mark(file->absoluteFilePath());
}
void ScriptEngine::unmark(File *file)
{
_database->unmark(file->absoluteFilePath());
}
bool ScriptEngine::isMarked(const File *file) const
{
return _database->isMarked(file->absoluteFilePath());
}
void ScriptEngine::run()
{
QJSValue jsPaths = _jsEngine->newArray(_paths.size());
for(qsizetype i=0; i<_paths.size(); i++)
jsPaths.setProperty(i, _jsEngine->newQObject(new File(_paths[i], this)));
_jsEngine->globalObject().setProperty("files", jsPaths);
QFile scriptFile(_scriptPath);
if(!scriptFile.open(QIODevice::ReadOnly))
return;
QTextStream stream(&scriptFile);
QString contents = stream.readAll();
scriptFile.close();
QJSValue result = _jsEngine->evaluate(contents, _scriptPath);
qDebug() << result.isError() << result.toString();
if(result.isError())
{
QString error = result.property("name").toString() + " on line " + result.property("lineNumber").toString() + " : " + result.toString();
error += "\n" + result.property("stack").toString();
emit newMessage(error);
}
emit finished();
}
void File::loadFitsKeywords()
{
if(!_fitsKeywordsLoaded)
{
_fitsKeywordsLoaded = true;
ImageInfoData info;
if(suffix() == "xisf")
{
readXISFHeader(_path, info);
}
else if(suffix() == "fits")
{
readFITSHeader(_path, info);
}
else return;
for(const FITSRecord &record : info.fitsHeader)
{
_fitsKeywords[record.key] = record.value.toString();
}
}
}
File::File(const QString &path, Script::ScriptEngine *engine) :
_engine(engine),
_path(path),
_info(path)
{
}
QString File::fileName() const
{
return _info.fileName();
}
QString File::absoluteFilePath() const
{
return _info.absoluteFilePath();
}
QString File::absolutePath() const
{
return _info.absolutePath();
}
QString File::baseName() const
{
return _info.baseName();
}
QString File::completeBaseName() const
{
return _info.completeBaseName();
}
QString File::suffix() const
{
return _info.suffix();
}
qint64 File::size() const
{
return _info.size();
}
QStringList File::fitsKeywords()
{
QThread::msleep(500);
loadFitsKeywords();
return _fitsKeywords.keys();
}
QString File::fitsValue(const QString &key)
{
loadFitsKeywords();
if(_fitsKeywords.contains(key))
return _fitsKeywords[key];
else
return QString();
}
bool File::isMarked() const
{
return _engine->isMarked(this);
}
bool File::copy(const QString &newpath) const
{
return QFile::copy(_path, _engine->outputDir() + newpath);
}
bool File::move(const QString &newpath) const
{
return QFile::rename(_path, _engine->outputDir() + newpath);
}
bool File::convertTo(const QString &format)
{
_engine->reportError("Not implemented");
return false;
}
ScriptEngineThread::ScriptEngineThread(QObject *parent) : QObject(parent)
{
_thread = new QThread();
_thread->setObjectName("ScriptEngine");
_engine = new ScriptEngine;
_engine->moveToThread(_thread);
connect(_engine, &ScriptEngine::finished, _thread, &QThread::quit);
connect(_engine, &ScriptEngine::newMessage, this, &ScriptEngineThread::newMessage);
connect(_thread, &QThread::started, _engine, &ScriptEngine::run);
connect(_thread, &QThread::finished, _engine, &ScriptEngine::deleteLater);
connect(_thread, &QThread::finished, _thread, &QThread::deleteLater);
connect(_thread, &QThread::finished, this, &ScriptEngineThread::finished);
}
ScriptEngineThread::~ScriptEngineThread()
{
if(_engine)_engine->interrupt();
}
void ScriptEngineThread::setParams(const QString &scriptPath, const QStringList &paths, const QString &outputDir)
{
_engine->setParams(scriptPath, paths, outputDir);
}
void ScriptEngineThread::start()
{
_thread->start();
}
void ScriptEngineThread::interrupt()
{
if(_engine)_engine->interrupt();
}
}
+84
View File
@@ -0,0 +1,84 @@
#ifndef SCRIPTENGINE_H
#define SCRIPTENGINE_H
#include <QObject>
#include <QJSEngine>
#include <QFileInfo>
#include <QThread>
#include "database.h"
namespace Script
{
class File;
class ScriptEngine : public QObject
{
Q_OBJECT
QJSEngine *_jsEngine;
Database *_database;
QString _scriptPath;
QString _outputDir;
QStringList _paths;
public:
explicit ScriptEngine(QObject *parent = nullptr);
void setParams(const QString &scriptPath, const QStringList &paths, const QString &outputDir);
void reportError(const QString &message);
const QString& outputDir() const;
void interrupt();
Q_INVOKABLE void log(const QString &message);
Q_INVOKABLE void mark(File *file);
Q_INVOKABLE void unmark(File *file);
Q_INVOKABLE bool isMarked(const File *file) const;
public slots:
void run();
signals:
void newMessage(const QString &message);
void finished();
};
class ScriptEngineThread : public QObject
{
Q_OBJECT
QThread *_thread;
ScriptEngine *_engine;
public:
ScriptEngineThread(QObject *parent = nullptr);
~ScriptEngineThread();
void setParams(const QString &scriptPath, const QStringList &paths, const QString &outputDir);
void start();
void interrupt();
signals:
void newMessage(const QString &message);
void finished();
};
class File : public QObject
{
Q_OBJECT
ScriptEngine *_engine;
QString _path;
QFileInfo _info;
bool _fitsKeywordsLoaded = false;
QMap<QString, QString> _fitsKeywords;
void loadFitsKeywords();
public:
explicit File(const QString &path, ScriptEngine *engine);
Q_INVOKABLE QString fileName() const;
Q_INVOKABLE QString absoluteFilePath() const;
Q_INVOKABLE QString absolutePath() const;
Q_INVOKABLE QString baseName() const;
Q_INVOKABLE QString completeBaseName() const;
Q_INVOKABLE QString suffix() const;
Q_INVOKABLE qint64 size() const;
Q_INVOKABLE QStringList fitsKeywords();
Q_INVOKABLE QString fitsValue(const QString &key);
Q_INVOKABLE bool isMarked() const;
Q_INVOKABLE bool copy(const QString &newpath) const;
Q_INVOKABLE bool move(const QString &newpath) const;
Q_INVOKABLE bool convertTo(const QString &format);
};
}
#endif // SCRIPTENGINE_H