// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "JFJochProcessController.h" #include "../reader/JFJochHDF5Reader.h" #include JFJochProcessController::JFJochProcessController(QObject *parent) : QObject(parent) { qRegisterMetaType("ProcessResult"); } JFJochProcessController::~JFJochProcessController() { cancel(); joinWorker_(); } void JFJochProcessController::joinWorker_() { if (worker_.joinable()) worker_.join(); } void JFJochProcessController::start(const QString &file_path, DiffractionExperiment experiment, PixelMask pixel_mask, ProcessConfig config) { if (running_.exchange(true)) return; // a job is already running cancel_pending_ = false; joinWorker_(); // reap the previous (finished) worker, if any worker_ = std::thread(&JFJochProcessController::run_, this, file_path, std::move(experiment), std::move(pixel_mask), std::move(config)); emit started(); } void JFJochProcessController::cancel() { cancel_pending_ = true; if (auto *p = active_.load()) p->Cancel(); } void JFJochProcessController::run_(QString file_path, DiffractionExperiment experiment, PixelMask pixel_mask, ProcessConfig config) { try { JFJochHDF5Reader reader; reader.ReadFile(file_path.toStdString()); JFJochProcess process(reader, std::move(experiment), std::move(pixel_mask), std::move(config)); active_ = &process; if (cancel_pending_) process.Cancel(); ProcessResult result = process.Run(this); active_ = nullptr; running_ = false; emit finished(result); } catch (const std::exception &e) { active_ = nullptr; running_ = false; emit failed(QString::fromStdString(e.what())); } } void JFJochProcessController::OnPhase(const std::string &phase) { emit phaseChanged(QString::fromStdString(phase)); } void JFJochProcessController::OnProgress(uint64_t done, uint64_t total) { // Throttle to ~200 updates so a long run does not flood the GUI event queue. const uint64_t step = total > 200 ? total / 200 : 1; if (done == total || done % step == 0) emit progress(done, total); }