8#include "capturecountswidget.h"
10#include "ekos/manager.h"
11#include "ekos/scheduler/schedulerjob.h"
12#include "ekos/scheduler/schedulermodulestate.h"
13#include "ekos/capture/capture.h"
14#include "ekos/capture/sequencejob.h"
16#include <ekos_capture_debug.h>
18using Ekos::SequenceJob;
20CaptureCountsWidget::CaptureCountsWidget(
QWidget *parent) :
QWidget(parent)
26 textView->setVisible(
false);
27 graphicalView->setVisible(
true);
28 Options::setUseGraphicalCountsDisplay(
true);
32 textView->setVisible(
true);
33 graphicalView->setVisible(
false);
34 Options::setUseGraphicalCountsDisplay(
false);
38 graphicalView->setVisible(Options::useGraphicalCountsDisplay());
39 textView->setVisible(!Options::useGraphicalCountsDisplay());
42 gr_sequenceProgressBar->setDecimals(0);
43 gr_overallProgressBar->setDecimals(0);
48void CaptureCountsWidget::setCurrentTrainName(
const QString &name)
50 m_currentTrainName =
name;
51 showCurrentCameraInfo();
52 refreshCaptureCounters(name);
55void CaptureCountsWidget::refreshImageCounts(
const QString &trainname)
57 if (imageCounts[trainname].changed)
59 imageProgress->setRange(0,
int(std::ceil(imageCounts[trainname].totalTime)));
60 imageProgress->setValue(
int(std::ceil(imageCounts[trainname].totalTime - imageCounts[trainname].remainingTime)));
61 gr_imageProgress->setRange(0,
int(std::ceil(imageCounts[trainname].totalTime)));
62 gr_imageProgress->setValue(imageProgress->value());
64 frameRemainingTime->setText(imageCounts[trainname].countDown.toString(
"hh:mm:ss"));
65 gr_frameRemainingTime->setText(frameRemainingTime->text());
67 imageCounts[trainname].changed =
false;
69 else if(isCaptureActive(trainname) ==
false)
71 imageProgress->setValue(0);
72 gr_imageProgress->setValue(0);
78 imageCounts[trainname].countDown.setHMS(0, 0, 0);
79 imageCounts[trainname].countDown = imageCounts[trainname].countDown.addSecs(
int(std::round(job->getExposeLeft())));
80 if (imageCounts[trainname].countDown.hour() == 23)
81 imageCounts[trainname].countDown.setHMS(0, 0, 0);
83 const double total = job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble();
84 const double remaining = job->getExposeLeft();
87 imageCounts[trainname].changed = fabs(total - imageCounts[trainname].totalTime) >= 1.0 ||
88 fabs(remaining - imageCounts[trainname].remainingTime) >= 1.0;
89 imageCounts[trainname].totalTime = total;
90 imageCounts[trainname].remainingTime = remaining;
92 refreshImageCounts(trainname);
95void CaptureCountsWidget::updateDownloadProgress(
double timeLeft,
const QString &trainname)
97 imageCounts[trainname].countDown.setHMS(0, 0, 0);
98 imageCounts[trainname].countDown = imageCounts[trainname].countDown.addSecs(
int(std::ceil(timeLeft)));
99 frameRemainingTime->setText(imageCounts[trainname].countDown.toString(
"hh:mm:ss"));
104 m_schedulerModuleState = state;
107void CaptureCountsWidget::updateCaptureCountDown(
int delta)
110 for (
const QString &trainname : totalCounts.keys())
112 totalCounts[trainname].countDown = totalCounts[trainname].countDown.addSecs(delta);
113 jobCounts[trainname].countDown = jobCounts[trainname].countDown.addSecs(delta);
114 sequenceCounts[trainname].countDown = sequenceCounts[trainname].countDown.addSecs(delta);
117 if (totalCounts[trainname].countDown.hour() == 23)
118 totalCounts[trainname].countDown.setHMS(0, 0, 0);
119 if (jobCounts[trainname].countDown.hour() == 23)
120 jobCounts[trainname].countDown.setHMS(0, 0, 0);
121 if (sequenceCounts[trainname].countDown.hour() == 23)
122 sequenceCounts[trainname].countDown.setHMS(0, 0, 0);
126 if (m_schedulerModuleState ==
nullptr || m_schedulerModuleState->activeJob() ==
nullptr ||
127 m_schedulerModuleState->activeJob()->getCompletionCondition() != Ekos::FINISH_LOOP)
129 overallRemainingTime->setText(totalCounts[m_currentTrainName].countDown.toString(
"hh:mm:ss"));
130 gr_overallRemainingTime->setText(overallRemainingTime->text());
132 if (!m_captureProcess->isActiveJobPreview() && isCaptureActive(m_currentTrainName))
134 jobRemainingTime->setText(jobCounts[m_currentTrainName].countDown.toString(
"hh:mm:ss"));
135 sequenceRemainingTime->setText(sequenceCounts[m_currentTrainName].countDown.toString(
"hh:mm:ss"));
136 gr_sequenceRemainingTime->setText(sequenceRemainingTime->text());
140 jobRemainingTime->setText(
"--:--:--");
141 sequenceRemainingTime->setText(
"--:--:--");
142 gr_sequenceRemainingTime->setText(
"--:--:--");
146void CaptureCountsWidget::reset()
149 gr_imageProgress->setValue(0);
150 gr_frameLabel->setText(
"");
151 gr_frameRemainingTime->setText(
"--:--:--");
152 gr_frameDetailsLabel->setText(
"");
153 gr_sequenceLabel->setText(
i18n(
"Sequence"));
154 gr_sequenceProgressBar->setValue(0);
155 gr_sequenceRemainingTime->setText(
"--:--:--");
156 gr_overallLabel->setText(
i18n(
"Overall"));
157 gr_overallProgressBar->setValue(0);
158 gr_overallRemainingTime->setText(
"--:--:--");
161 imageProgress->setValue(0);
163 frameRemainingTime->setText(
"");
165 overallRemainingTime->setText(
"--:--:--");
166 jobRemainingTime->setText(
"--:--:--");
167 sequenceRemainingTime->setText(
"--:--:--");
181 else if (type ==
"Flat")
193void CaptureCountsWidget::setFrameInfo(
const QString frametype,
const QString filter,
const double exptime,
const int xBin,
194 const int yBin,
const double gain)
198 frameInfoLabel->setText(
"");
199 frameDetailsLabel->setText(
"");
200 gr_frameRemainingTime->setText(
"");
204 frameInfoLabel->setText(QString(
"%1").arg(frameLabel(frametype, filter)));
205 gr_frameLabel->setText(frameInfoLabel->text());
206 QString details =
"";
208 details.
append(QString(
"%1: %2 sec").arg(
i18n(
"Exposure")).arg(exptime, 0,
'f', exptime < 1 ? 2 : exptime < 5 ? 1 : 0));
209 if (xBin > 0 && yBin > 0)
210 details.
append(QString(
", bin: %1x%2").arg(xBin).arg(yBin));
212 details.
append(QString(
", gain: %1").arg(gain, 0,
'f', 1));
214 frameDetailsLabel->setText(details);
215 gr_frameDetailsLabel->setText(details);
222 captureStates[trainname] =
status;
224 totalCounts[trainname].countDown.setHMS(0, 0, 0);
225 totalCounts[trainname].remainingTime = 0;
227 m_isPreview = isPreview;
230 QSharedPointer<Ekos::Camera> selected_cam;
231 for (QSharedPointer<Ekos::Camera> camera : m_captureProcess->cameras())
233 if (camera->opticalTrain() == trainname)
235 selected_cam = camera;
240 if (selected_cam.
isNull())
242 qCWarning(KSTARS_EKOS_CAPTURE) <<
"No matching camera found" << m_currentTrainName;
249 jobCounts[trainname].remainingTime = selected_cam->state()->overallRemainingTime();
250 jobCounts[trainname].count = 0, jobCounts[trainname].completed = 0;
251 for (
int i = 0; i < selected_cam->state()->allJobs().count(); i++)
253 jobCounts[trainname].count += selected_cam->state()->jobImageCount(i);
254 jobCounts[trainname].completed += selected_cam->state()->jobImageProgress(i);
257 Ekos::SchedulerJob *activeJob = m_schedulerModuleState->activeJob(trainname);
258 if (m_schedulerModuleState !=
nullptr && activeJob !=
nullptr)
261 totalCounts[trainname].completed = activeJob->getCompletedCount();
262 totalCounts[trainname].count = activeJob->getSequenceCount();
263 if (activeJob->getEstimatedTime() > 0)
264 totalCounts[trainname].remainingTime = int(activeJob->getEstimatedTime());
268 totalCounts[trainname].remainingTime = jobCounts[trainname].remainingTime;
269 totalCounts[trainname].count = jobCounts[trainname].count;
270 totalCounts[trainname].completed = jobCounts[trainname].completed;
274 sequenceCounts[trainname].countDown.setHMS(0, 0, 0);
275 sequenceCounts[trainname].countDown = sequenceCounts[trainname].countDown.addSecs(
276 selected_cam->state()->activeJobRemainingTime());
279 if (m_schedulerModuleState !=
nullptr && activeJob !=
nullptr)
281 jobCounts[trainname].countDown.setHMS(0, 0, 0);
282 jobCounts[trainname].countDown = jobCounts[trainname].countDown.addSecs(selected_cam->state()->overallRemainingTime());
291 refreshImageCounts(trainname);
292 updateCaptureCountDown(0);
296 if (m_currentTrainName == trainname)
297 refreshCaptureCounters(trainname);
301void CaptureCountsWidget::updateJobProgress(CaptureProcessOverlay::FrameData data,
const QString &trainname)
303 m_currentFrame[trainname] = data;
306 if (trainname == m_currentTrainName)
307 showCurrentCameraInfo();
310void CaptureCountsWidget::showCurrentCameraInfo()
312 if (!m_currentFrame.contains(m_currentTrainName))
314 qCWarning(KSTARS_EKOS_CAPTURE) <<
"No frame info available for" << m_currentTrainName;
318 auto data = m_currentFrame[m_currentTrainName];
320 if (data.jobType == SequenceJob::JOBTYPE_PREVIEW)
321 setFrameInfo(
i18n(
"Preview"), data.filterName, data.exptime, data.binning.
x(), data.binning.
y(), data.gain);
323 setFrameInfo(CCDFrameTypeNames[data.frameType], data.filterName, data.exptime, data.binning.
x(),
324 data.binning.
y(), data.gain);
327 gr_sequenceProgressBar->setRange(0, data.count);
328 gr_sequenceProgressBar->setValue(data.completed);
329 if (data.jobType == SequenceJob::JOBTYPE_PREVIEW)
330 sequenceLabel->setText(QString(
"%1").arg(frameLabel(CCDFrameTypeNames[data.frameType], data.filterName)));
332 sequenceLabel->setText(QString(
"%1 (%3/%4)")
333 .arg(frameLabel(CCDFrameTypeNames[data.frameType], data.filterName)).arg(data.completed).arg(data.count));
335 gr_sequenceLabel->setText(sequenceLabel->text());
338void CaptureCountsWidget::refreshCaptureCounters(
const QString &trainname)
340 QString total_label =
"Total";
341 bool infinite_loop =
false;
342 Ekos::SchedulerJob *activeJob = m_schedulerModuleState->activeJob(trainname);
343 bool isCapturing = isCaptureActive(trainname);
344 if (m_schedulerModuleState !=
nullptr && activeJob !=
nullptr)
346 infinite_loop = (activeJob->getCompletionCondition() == Ekos::FINISH_LOOP);
347 total_label = activeJob->getName();
350 if (infinite_loop ==
true || isCapturing ==
false)
352 overallRemainingTime->setText(
"--:--:--");
353 gr_overallProgressBar->setRange(0, 1);
354 gr_overallProgressBar->setValue(0);
355 gr_overallRemainingTime->setText(overallRemainingTime->text());
359 totalCounts[trainname].countDown = totalCounts[trainname].countDown.addSecs(totalCounts[trainname].remainingTime);
360 gr_overallProgressBar->setRange(0, totalCounts[trainname].count);
361 gr_overallProgressBar->setValue(totalCounts[trainname].completed);
366 overallLabel->setText(QString(
"%1").arg(total_label));
368 overallLabel->setText(QString(
"%1 (%2/%3)")
370 .arg(totalCounts[trainname].completed)
371 .arg(infinite_loop ? QString(
"-") :
QString::number(totalCounts[trainname].count)));
372 gr_overallLabel->setText(overallLabel->text());
375 bool show_job_progress = (m_schedulerModuleState !=
nullptr && activeJob !=
nullptr);
376 jobLabel->setVisible(show_job_progress);
377 jobRemainingTime->setVisible(show_job_progress);
378 if (show_job_progress)
380 jobLabel->setText(QString(
"Job (%1/%2)")
381 .arg(jobCounts[trainname].completed)
382 .arg(jobCounts[trainname].count));
389 if (! captureStates.contains(trainname))
392 return captureStates[trainname];
395bool CaptureCountsWidget::isCaptureActive(
const QString &trainname)
406void CaptureCountsWidget::setEnabled(
bool enabled)
409 overallLabel->setEnabled(
enabled);
410 gr_overallLabel->setEnabled(
enabled);
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
CaptureState
Capture states.
QString name(StandardAction id)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
bool isNull() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)