File indexing completed on 2024-04-28 03:43:13

0001 /*
0002     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003     SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "capturecountswidget.h"
0009 #include "Options.h"
0010 #include "ekos/manager.h"
0011 #include "ekos/scheduler/scheduler.h"
0012 #include "ekos/capture/capture.h"
0013 #include "ekos/capture/sequencejob.h"
0014 
0015 using Ekos::SequenceJob;
0016 
0017 CaptureCountsWidget::CaptureCountsWidget(QWidget *parent) : QWidget(parent)
0018 {
0019     setupUi(this);
0020     // switch between stacked views
0021     connect(switchToGraphicsButton, &QPushButton::clicked, this, [this]()
0022     {
0023         textView->setVisible(false);
0024         graphicalView->setVisible(true);
0025         Options::setUseGraphicalCountsDisplay(true);
0026     });
0027     connect(switchToTextButton, &QPushButton::clicked, this, [this]()
0028     {
0029         textView->setVisible(true);
0030         graphicalView->setVisible(false);
0031         Options::setUseGraphicalCountsDisplay(false);
0032     });
0033 
0034     // start with the last used view
0035     graphicalView->setVisible(Options::useGraphicalCountsDisplay());
0036     textView->setVisible(!Options::useGraphicalCountsDisplay());
0037 
0038     // setup graphical view
0039     gr_sequenceProgressBar->setDecimals(0);
0040     gr_overallProgressBar->setDecimals(0);
0041 
0042     reset();
0043 }
0044 
0045 void CaptureCountsWidget::updateExposureProgress(Ekos::SequenceJob *job)
0046 {
0047     imageCountDown.setHMS(0, 0, 0);
0048     imageCountDown = imageCountDown.addSecs(int(std::round(job->getExposeLeft())));
0049     if (imageCountDown.hour() == 23)
0050         imageCountDown.setHMS(0, 0, 0);
0051 
0052     imageProgress->setRange(0, int(std::ceil(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble())));
0053     imageProgress->setValue(int(std::ceil(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble() - job->getExposeLeft())));
0054     gr_imageProgress->setRange(0, int(std::ceil(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble())));
0055     gr_imageProgress->setValue(imageProgress->value());
0056 
0057     frameRemainingTime->setText(imageCountDown.toString("hh:mm:ss"));
0058     gr_frameRemainingTime->setText(frameRemainingTime->text());
0059 }
0060 
0061 void CaptureCountsWidget::updateDownloadProgress(double timeLeft)
0062 {
0063     imageCountDown.setHMS(0, 0, 0);
0064     imageCountDown = imageCountDown.addSecs(int(std::ceil(timeLeft)));
0065     frameRemainingTime->setText(imageCountDown.toString("hh:mm:ss"));
0066 }
0067 
0068 void CaptureCountsWidget::updateCaptureCountDown(int delta)
0069 {
0070     overallCountDown  = overallCountDown.addSecs(delta);
0071     jobCountDown      = jobCountDown.addSecs(delta);
0072     sequenceCountDown = sequenceCountDown.addSecs(delta);
0073 
0074     // ensure that count downs do not overshoot
0075     if (overallCountDown.hour() == 23)
0076         overallCountDown.setHMS(0, 0, 0);
0077     if (jobCountDown.hour() == 23)
0078         jobCountDown.setHMS(0, 0, 0);
0079     if (sequenceCountDown.hour() == 23)
0080         sequenceCountDown.setHMS(0, 0, 0);
0081 
0082     // do not change overall remaining time if scheduler is in endless loop
0083     if (schedulerProcess == nullptr || schedulerProcess->activeJob() == nullptr ||
0084             schedulerProcess->activeJob()->getCompletionCondition() != Ekos::FINISH_LOOP)
0085     {
0086         overallRemainingTime->setText(overallCountDown.toString("hh:mm:ss"));
0087         gr_overallRemainingTime->setText(overallRemainingTime->text());
0088     }
0089     jobRemainingTime->setText(jobCountDown.toString("hh:mm:ss"));
0090     sequenceRemainingTime->setText(sequenceCountDown.toString("hh:mm:ss"));
0091     gr_sequenceRemainingTime->setText(sequenceRemainingTime->text());
0092 }
0093 
0094 void CaptureCountsWidget::reset()
0095 {
0096     // reset graphical view
0097     gr_imageProgress->setValue(0);
0098     gr_frameLabel->setText("");
0099     gr_frameRemainingTime->setText("--:--:--");
0100     gr_frameDetailsLabel->setText("");
0101     gr_sequenceLabel->setText(i18n("Sequence"));
0102     gr_sequenceProgressBar->setValue(0);
0103     gr_sequenceRemainingTime->setText("--:--:--");
0104     gr_overallLabel->setText(i18n("Overall"));
0105     gr_overallProgressBar->setValue(0);
0106     gr_overallRemainingTime->setText("--:--:--");
0107 
0108     // reset text view
0109     imageProgress->setValue(0);
0110     setFrameInfo("");
0111     frameRemainingTime->setText("");
0112 
0113     overallRemainingTime->setText("--:--:--");
0114     jobRemainingTime->setText("--:--:--");
0115     sequenceRemainingTime->setText("--:--:--");
0116 }
0117 
0118 namespace
0119 {
0120 QString frameLabel(const QString &type, const QString &filter)
0121 {
0122     if (type == "Light")
0123     {
0124         if (filter.size() == 0)
0125             return type;
0126         else
0127             return filter;
0128     }
0129     else if (type == "Flat")
0130     {
0131         if (filter.size() == 0)
0132             return type;
0133         else
0134             return QString("%1 %2").arg(filter).arg(type);
0135     }
0136     else
0137         return type;
0138 }
0139 }
0140 
0141 void CaptureCountsWidget::setFrameInfo(const QString frametype, const QString filter, const double exptime, const int xBin,
0142                                        const int yBin, const double gain)
0143 {
0144     if (frametype == "")
0145     {
0146         frameInfoLabel->setText("");
0147         frameDetailsLabel->setText("");
0148         gr_frameRemainingTime->setText("");
0149     }
0150     else
0151     {
0152         frameInfoLabel->setText(QString("%1").arg(frameLabel(frametype, filter)));
0153         gr_frameLabel->setText(frameInfoLabel->text());
0154         QString details = "";
0155         if (exptime > 0)
0156             details.append(QString("%1: %2 sec").arg(i18n("Exposure")).arg(exptime, 0, 'f', exptime < 1 ? 2 : exptime < 5 ? 1 : 0));
0157         if (xBin > 0 && yBin > 0)
0158             details.append(QString(", bin: %1x%2").arg(xBin).arg(yBin));
0159         if (gain >= 0)
0160             details.append(QString(", gain: %1").arg(gain, 0, 'f', 1));
0161 
0162         frameDetailsLabel->setText(details);
0163         gr_frameDetailsLabel->setText(details);
0164     }
0165 }
0166 
0167 void CaptureCountsWidget::updateCaptureStatus(Ekos::CaptureState status)
0168 {
0169     overallCountDown.setHMS(0, 0, 0);
0170     bool infinite_loop = false;
0171     int total_remaining_time = 0, total_completed = 0, total_count = 0;
0172     double total_percentage = 0;
0173     // use this value if no scheduler is running and job name otherwise
0174     QString total_label = "Total";
0175 
0176     // determine total number of frames and completed ones - used either for
0177     // total numbers if scheduler is not used - and for job figures in the text
0178     // display if the scheduler is used
0179     double capture_total_percentage = captureProcess->getProgressPercentage();
0180     int    capture_remaining_time   = captureProcess->getOverallRemainingTime();
0181     int capture_total_count = 0, capture_total_completed = 0;
0182     for (int i = 0; i < captureProcess->getJobCount(); i++)
0183     {
0184         capture_total_count     += captureProcess->getJobImageCount(i);
0185         capture_total_completed += captureProcess->getJobImageProgress(i);
0186     }
0187 
0188 
0189     if (schedulerProcess != nullptr && schedulerProcess->activeJob() != nullptr)
0190     {
0191         total_label = schedulerProcess->getCurrentJobName();
0192         // FIXME: accessing the completed count might be one too low due to concurrency of updating the count and this loop
0193         total_completed = schedulerProcess->activeJob()->getCompletedCount();
0194         total_count     = schedulerProcess->activeJob()->getSequenceCount();
0195         infinite_loop   = (schedulerProcess->activeJob()->getCompletionCondition() == Ekos::FINISH_LOOP);
0196         if (total_count > 0)
0197             total_percentage = (100 * total_completed) / total_count;
0198         if (schedulerProcess->activeJob()->getEstimatedTime() > 0)
0199             total_remaining_time = int(schedulerProcess->activeJob()->getEstimatedTime());
0200     }
0201     else
0202     {
0203         total_percentage     = capture_total_percentage;
0204         total_remaining_time = capture_remaining_time;
0205         total_count          = capture_total_count;
0206         total_completed      = capture_total_completed;
0207     }
0208 
0209     switch (status)
0210     {
0211         case Ekos::CAPTURE_IDLE:
0212             // do nothing
0213             break;
0214         case Ekos::CAPTURE_ABORTED:
0215             reset();
0216             break;
0217         default:
0218             if (infinite_loop == true)
0219             {
0220                 overallRemainingTime->setText("--:--:--");
0221                 gr_overallProgressBar->setValue(0);
0222                 gr_overallRemainingTime->setText(overallRemainingTime->text());
0223             }
0224             else
0225             {
0226                 overallCountDown = overallCountDown.addSecs(total_remaining_time);
0227                 gr_overallProgressBar->setValue(total_percentage);
0228             }
0229 
0230             // display overall remainings
0231             overallLabel->setText(QString("%1 (%2/%3)")
0232                                   .arg(total_label)
0233                                   .arg(total_completed)
0234                                   .arg(infinite_loop ? QString("-") : QString::number(total_count)));
0235             gr_overallLabel->setText(overallLabel->text());
0236 
0237             // update job remaining time if run from the scheduler
0238             bool show_job_progress = (schedulerProcess != nullptr && schedulerProcess->activeJob() != nullptr);
0239             jobLabel->setVisible(show_job_progress);
0240             jobRemainingTime->setVisible(show_job_progress);
0241             if (show_job_progress)
0242             {
0243                 jobCountDown.setHMS(0, 0, 0);
0244                 jobCountDown = jobCountDown.addSecs(captureProcess->getOverallRemainingTime());
0245                 jobLabel->setText(QString("Job (%1/%2)")
0246                                   .arg(capture_total_completed)
0247                                   .arg(capture_total_count));
0248             }
0249 
0250             // update sequence remaining time
0251             sequenceCountDown.setHMS(0, 0, 0);
0252             sequenceCountDown = sequenceCountDown.addSecs(captureProcess->getActiveJobRemainingTime());
0253     }
0254 }
0255 
0256 void CaptureCountsWidget::updateJobProgress(Ekos::SequenceJob *job)
0257 {
0258     // display informations about the current active capture
0259     if (job->jobType() == SequenceJob::JOBTYPE_PREVIEW)
0260         setFrameInfo(i18n("Preview"),  job->getCoreProperty(SequenceJob::SJ_Filter).toString(),
0261                      job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().x(),
0262                      job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().y(), job->getCoreProperty(SequenceJob::SJ_Gain).toDouble());
0263     else
0264         setFrameInfo(CCDFrameTypeNames[job->getFrameType()], job->getCoreProperty(SequenceJob::SJ_Filter).toString(),
0265                      job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().x(),
0266                      job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().y(), job->getCoreProperty(SequenceJob::SJ_Gain).toDouble());
0267 
0268     // display sequence progress in the graphical view
0269     gr_sequenceProgressBar->setRange(0, job->getCoreProperty(SequenceJob::SJ_Count).toInt());
0270     gr_sequenceProgressBar->setValue(job->getCompleted());
0271     sequenceLabel->setText(QString("%1 (%3/%4)")
0272                            .arg(frameLabel(CCDFrameTypeNames[job->getFrameType()],
0273                                            job->getCoreProperty(SequenceJob::SJ_Filter).toString()))
0274                            .arg(job->getCompleted()).arg(job->getCoreProperty(SequenceJob::SJ_Count).toInt()));
0275     gr_sequenceLabel->setText(sequenceLabel->text());
0276 }
0277 
0278 void CaptureCountsWidget::setEnabled(bool enabled)
0279 {
0280     QWidget::setEnabled(enabled);
0281     overallLabel->setEnabled(enabled);
0282     gr_overallLabel->setEnabled(enabled);
0283 }