1 /*
2     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
3     SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "capturecountswidget.h"
9 #include "Options.h"
10 #include "ekos/ekos.h"
11 #include "ekos/manager.h"
12 
CaptureCountsWidget(QWidget * parent)13 CaptureCountsWidget::CaptureCountsWidget(QWidget *parent) : QWidget(parent)
14 {
15     setupUi(this);
16     // switch between stacked views
17     connect(switchToGraphicsButton, &QPushButton::clicked, this, [this]() {textView->setVisible(false); graphicalView->setVisible(true); Options::setUseGraphicalCountsDisplay(true);});
18     connect(switchToTextButton, &QPushButton::clicked, this, [this]() {textView->setVisible(true); graphicalView->setVisible(false);Options::setUseGraphicalCountsDisplay(false);});
19 
20     // start with the last used view
21     graphicalView->setVisible(Options::useGraphicalCountsDisplay());
22     textView->setVisible(!Options::useGraphicalCountsDisplay());
23 
24     // setup graphical view
25     gr_sequenceProgressBar->setDecimals(0);
26     gr_overallProgressBar->setDecimals(0);
27 
28     reset();
29 }
30 
updateExposureProgress(Ekos::SequenceJob * job)31 void CaptureCountsWidget::updateExposureProgress(Ekos::SequenceJob *job)
32 {
33     imageCountDown.setHMS(0, 0, 0);
34     imageCountDown = imageCountDown.addSecs(int(std::round(job->getExposeLeft())));
35     if (imageCountDown.hour() == 23)
36         imageCountDown.setHMS(0, 0, 0);
37 
38     imageProgress->setRange(0, int(std::ceil(job->getExposure())));
39     imageProgress->setValue(int(std::ceil(job->getExposure() - job->getExposeLeft())));
40     gr_imageProgress->setRange(0, int(std::ceil(job->getExposure())));
41     gr_imageProgress->setValue(imageProgress->value());
42 
43     frameRemainingTime->setText(imageCountDown.toString("hh:mm:ss"));
44     gr_frameRemainingTime->setText(frameRemainingTime->text());
45 }
46 
updateDownloadProgress(double timeLeft)47 void CaptureCountsWidget::updateDownloadProgress(double timeLeft)
48 {
49     imageCountDown.setHMS(0, 0, 0);
50     imageCountDown = imageCountDown.addSecs(int(std::ceil(timeLeft)));
51     frameRemainingTime->setText(imageCountDown.toString("hh:mm:ss"));
52 }
53 
updateCaptureCountDown(int delta)54 void CaptureCountsWidget::updateCaptureCountDown(int delta)
55 {
56     overallCountDown  = overallCountDown.addSecs(delta);
57     jobCountDown      = jobCountDown.addSecs(delta);
58     sequenceCountDown = sequenceCountDown.addSecs(delta);
59 
60     // ensure that count downs do not overshoot
61     if (overallCountDown.hour() == 23)
62         overallCountDown.setHMS(0, 0, 0);
63     if (jobCountDown.hour() == 23)
64         jobCountDown.setHMS(0, 0, 0);
65     if (sequenceCountDown.hour() == 23)
66         sequenceCountDown.setHMS(0, 0, 0);
67 
68     // do not change overall remaining time if scheduler is in endless loop
69     if (schedulerProcess == nullptr || schedulerProcess->getCurrentJob() == nullptr ||
70         schedulerProcess->getCurrentJob()->getCompletionCondition() != SchedulerJob::FINISH_LOOP)
71     {
72         overallRemainingTime->setText(overallCountDown.toString("hh:mm:ss"));
73         gr_overallRemainingTime->setText(overallRemainingTime->text());
74     }
75     jobRemainingTime->setText(jobCountDown.toString("hh:mm:ss"));
76     sequenceRemainingTime->setText(sequenceCountDown.toString("hh:mm:ss"));
77     gr_sequenceRemainingTime->setText(sequenceRemainingTime->text());
78 }
79 
reset()80 void CaptureCountsWidget::reset()
81 {
82     // reset graphical view
83     gr_imageProgress->setValue(0);
84     gr_frameLabel->setText("");
85     gr_frameRemainingTime->setText("--:--:--");
86     gr_frameDetailsLabel->setText("");
87     gr_sequenceLabel->setText(i18n("Sequence"));
88     gr_sequenceProgressBar->setValue(0);
89     gr_sequenceRemainingTime->setText("--:--:--");
90     gr_overallLabel->setText(i18n("Overall"));
91     gr_overallProgressBar->setValue(0);
92     gr_overallRemainingTime->setText("--:--:--");
93 
94     // reset text view
95     imageProgress->setValue(0);
96     setFrameInfo("");
97     frameRemainingTime->setText("");
98 
99     overallRemainingTime->setText("--:--:--");
100     jobRemainingTime->setText("--:--:--");
101     sequenceRemainingTime->setText("--:--:--");
102 }
103 
setFrameInfo(const QString frametype,const QString filter,const double exptime,const int xBin,const int yBin,const double gain)104 void CaptureCountsWidget::setFrameInfo(const QString frametype, const QString filter, const double exptime, const int xBin, const int yBin, const double gain)
105 {
106     if (frametype == "")
107     {
108         frameInfoLabel->setText("");
109         frameDetailsLabel->setText("");
110         gr_frameRemainingTime->setText("");
111     }
112     else
113     {
114         frameInfoLabel->setText(QString("%1 %2").arg(frametype).arg(filter));
115         gr_frameLabel->setText(frameInfoLabel->text());
116         QString details = "";
117         if (exptime > 0)
118                 details.append(QString("%1: %2 sec").arg(i18n("Exposure")).arg(exptime, 0, 'f', exptime < 1 ? 2: exptime < 5 ? 1 : 0));
119         if (xBin > 0 && yBin > 0)
120             details.append(QString(", bin: %1x%2").arg(xBin).arg(yBin));
121         if (gain >= 0)
122             details.append(QString(", gain: %1").arg(gain, 0, 'f', 1));
123 
124         frameDetailsLabel->setText(details);
125         gr_frameDetailsLabel->setText(details);
126     }
127 }
128 
updateCaptureStatus(Ekos::CaptureState status)129 void CaptureCountsWidget::updateCaptureStatus(Ekos::CaptureState status)
130 {
131     overallCountDown.setHMS(0, 0, 0);
132     bool infinite_loop = false;
133     int total_remaining_time = 0, total_completed = 0, total_count = 0;
134     double total_percentage = 0;
135     // use this value if no scheduler is running and job name otherwise
136     QString total_label = "Total";
137 
138     // determine total number of frames and completed ones - used either for
139     // total numbers if scheduler is not used - and for job figures in the text
140     // display if the scheduler is used
141     double capture_total_percentage = captureProcess->getProgressPercentage();
142     int    capture_remaining_time   = captureProcess->getOverallRemainingTime();
143     int capture_total_count = 0, capture_total_completed = 0;
144     for (int i = 0; i < captureProcess->getJobCount(); i++)
145     {
146         capture_total_count     += captureProcess->getJobImageCount(i);
147         capture_total_completed += captureProcess->getJobImageProgress(i);
148     }
149 
150 
151     if (schedulerProcess != nullptr && schedulerProcess->getCurrentJob() != nullptr)
152     {
153         total_label = schedulerProcess->getCurrentJobName();
154         // FIXME: accessing the completed count might be one too low due to concurrency of updating the count and this loop
155         total_completed = schedulerProcess->getCurrentJob()->getCompletedCount();
156         total_count     = schedulerProcess->getCurrentJob()->getSequenceCount();
157         infinite_loop   = (schedulerProcess->getCurrentJob()->getCompletionCondition() == SchedulerJob::FINISH_LOOP);
158         if (total_count > 0)
159             total_percentage = (100 * total_completed) / total_count;
160         if (schedulerProcess->getCurrentJob()->getEstimatedTime() > 0)
161             total_remaining_time = int(schedulerProcess->getCurrentJob()->getEstimatedTime());
162     }
163     else
164     {
165         total_percentage     = capture_total_percentage;
166         total_remaining_time = capture_remaining_time;
167         total_count          = capture_total_count;
168         total_completed      = capture_total_completed;
169     }
170 
171     switch (status)
172     {
173     case Ekos::CAPTURE_IDLE:
174         // do nothing
175         break;
176     case Ekos::CAPTURE_ABORTED:
177         reset();
178         break;
179      default:
180         if (infinite_loop == true)
181         {
182             overallRemainingTime->setText("--:--:--");
183             gr_overallProgressBar->setValue(0);
184             gr_overallRemainingTime->setText(overallRemainingTime->text());
185         }
186         else
187         {
188             overallCountDown = overallCountDown.addSecs(total_remaining_time);
189             gr_overallProgressBar->setValue(total_percentage);
190         }
191 
192         // display overall remainings
193         overallLabel->setText(QString("%1 (%2/%3)")
194                               .arg(total_label)
195                               .arg(total_completed)
196                               .arg(infinite_loop ? QString("-") : QString::number(total_count)));
197         gr_overallLabel->setText(overallLabel->text());
198 
199         // update job remaining time if run from the scheduler
200         bool show_job_progress = (schedulerProcess != nullptr && schedulerProcess->getCurrentJob() != nullptr);
201         jobLabel->setVisible(show_job_progress);
202         jobRemainingTime->setVisible(show_job_progress);
203         if (show_job_progress)
204         {
205             jobCountDown.setHMS(0, 0, 0);
206             jobCountDown = jobCountDown.addSecs(captureProcess->getOverallRemainingTime());
207             jobLabel->setText(QString("Job (%1/%2)")
208                                   .arg(capture_total_completed)
209                                   .arg(capture_total_count));
210         }
211 
212         // update sequence remaining time
213         sequenceCountDown.setHMS(0, 0, 0);
214         sequenceCountDown = sequenceCountDown.addSecs(captureProcess->getActiveJobRemainingTime());
215     }
216 }
217 
updateJobProgress(Ekos::SequenceJob * job)218 void CaptureCountsWidget::updateJobProgress(Ekos::SequenceJob *job)
219 {
220     // display informations about the current active capture
221     if (job->isPreview() == true)
222         setFrameInfo(i18n("Preview"),  job->getFilterName(), job->getExposure(), job->getXBin(), job->getYBin(), job->getGain());
223     else
224         setFrameInfo(CCDFrameTypeNames[job->getFrameType()], job->getFilterName(), job->getExposure(), job->getXBin(), job->getYBin(), job->getGain());
225 
226     // display sequence progress in the graphical view
227     gr_sequenceProgressBar->setRange(0, job->getCount());
228     gr_sequenceProgressBar->setValue(job->getCompleted());
229     sequenceLabel->setText(QString("%1 %2 (%3/%4)")
230                            .arg(CCDFrameTypeNames[job->getFrameType()])
231                            .arg(job->getFilterName())
232                            .arg(job->getCompleted()).arg(job->getCount()));
233     gr_sequenceLabel->setText(sequenceLabel->text());
234 }
235 
setEnabled(bool enabled)236 void CaptureCountsWidget::setEnabled(bool enabled)
237 {
238     QWidget::setEnabled(enabled);
239     overallLabel->setEnabled(enabled);
240     gr_overallLabel->setEnabled(enabled);
241 }
242