diff --git a/kstars/ekos/capture/capture.cpp b/kstars/ekos/capture/capture.cpp --- a/kstars/ekos/capture/capture.cpp +++ b/kstars/ekos/capture/capture.cpp @@ -365,6 +365,9 @@ Options::setAutoMeridianFlip(meridianCheck->isChecked()); Options::setAutoMeridianHours(meridianHours->value()); + // Reset progress option if there is no captured frame map set at the time of start - fixes the end-user setting the option just before starting + ignoreJobProgress = !capturedFramesMap.count() && Options::alwaysResetSequenceWhenStarting(); + if (queueTable->rowCount() == 0) { if (addJob() == false) @@ -382,8 +385,11 @@ } } + // If there are no idle nor aborted jobs, question is whether to reset and restart + // Scheduler will start a non-empty new job each time and doesn't use this execution path if (first_job == nullptr) { + // If we have at least one job that are in error, bail out, even if ignoring job progress foreach (SequenceJob *job, jobs) { if (job->getStatus() != SequenceJob::JOB_DONE) @@ -393,18 +399,29 @@ } } - if (KMessageBox::warningContinueCancel( - nullptr, - i18n("All jobs are complete. Do you want to reset the status of all jobs and restart capturing?"), - i18n("Reset job status"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), - "reset_job_complete_status_warning") != KMessageBox::Continue) - return; + // If we only have completed jobs and we don't ignore job progress, ask the end-user what to do + if (!ignoreJobProgress) + if(KMessageBox::warningContinueCancel( + nullptr, + i18n("All jobs are complete. Do you want to reset the status of all jobs and restart capturing?"), + i18n("Reset job status"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), + "reset_job_complete_status_warning") != KMessageBox::Continue) + return; + // If the end-user accepted to reset, reset all jobs and restart foreach (SequenceJob *job, jobs) job->resetStatus(); first_job = jobs.first(); } + // If we need to ignore job progress, systematically reset all jobs and restart + // Scheduler will never ignore job progress and doesn't use this path + else if (ignoreJobProgress) + { + appendLogText(i18n("Warning: option \"Always Reset Sequence When Starting\" is enabled and resets the sequence counts.")); + foreach (SequenceJob *job, jobs) + job->resetStatus(); + } // Record initialHA and initialMount position when we are starting fresh // If recovering from deviation error, these values should not be recorded. @@ -2110,10 +2127,6 @@ currentRow = queueTable->currentRow(); QTableWidgetItem *status = m_JobUnderEdit ? queueTable->item(currentRow, 0) : new QTableWidgetItem(); - status->setText(job->getStatusString()); - status->setTextAlignment(Qt::AlignHCenter); - status->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - job->setStatusCell(status); QTableWidgetItem *filter = m_JobUnderEdit ? queueTable->item(currentRow, 1) : new QTableWidgetItem(); @@ -2165,9 +2178,7 @@ iso->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); QTableWidgetItem *count = m_JobUnderEdit ? queueTable->item(currentRow, 6) : new QTableWidgetItem(); - count->setText(QString("%L1").arg(countIN->value())); - count->setTextAlignment(Qt::AlignHCenter); - count->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + job->setCountCell(count); jsonJob.insert("Count", count->text()); if (m_JobUnderEdit == false) @@ -2455,6 +2466,8 @@ activeJob->setJobProgressIgnored(true); activeJob->setCompleted(0); } + // We cannot rely on sequenceID to give us a count - if we don't ignore job progress, we leave the count as it was originally +#if 0 // If we cannot ignore job progress, then we set completed job number according to what // was found on the file system. else if (ignoreJobProgress == false) @@ -2465,6 +2478,7 @@ else activeJob->setCompleted(activeJob->getCount()); } +#endif // Check whether active job is complete by comparing required captures to what is already available if (activeJob->getCount() <= activeJob->getCompleted()) @@ -3161,8 +3175,6 @@ m_Dirty = false; delLilXML(xmlParser); - ignoreJobProgress = !(Options::rememberJobProgress()); - return true; } @@ -3587,28 +3599,39 @@ void Capture::resetJobs() { - if (KMessageBox::warningContinueCancel( - nullptr, i18n("Are you sure you want to reset status of all jobs?"), i18n("Reset job status"), - KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "reset_job_status_warning") != KMessageBox::Continue) + // Stop any running capture + stop(); + + // If a job is selected for edit, reset only that job + if (m_JobUnderEdit == true) { - return; + SequenceJob * job = jobs.at(queueTable->currentRow()); + if (nullptr != job) + job->resetStatus(); } + else + { + if (KMessageBox::warningContinueCancel( + nullptr, i18n("Are you sure you want to reset status of all jobs?"), i18n("Reset job status"), + KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "reset_job_status_warning") != KMessageBox::Continue) + { + return; + } - foreach (SequenceJob *job, jobs) - job->resetStatus(); - - // Reset active job pointer - activeJob = nullptr; - - stop(); + foreach (SequenceJob *job, jobs) + job->resetStatus(); + } + // Also reset the storage count for all jobs capturedFramesMap.clear(); - ignoreJobProgress = true; + // We're not controlled by the Scheduler, restore progress option + ignoreJobProgress = Options::alwaysResetSequenceWhenStarting(); } void Capture::ignoreSequenceHistory() { + // This function is called independently from the Scheduler or the UI, so honor the change ignoreJobProgress = true; } @@ -5513,9 +5536,8 @@ { capturedFramesMap[signature] = count; qCDebug(KSTARS_EKOS_CAPTURE) << QString("Client module indicates that storage for '%1' has already %2 captures processed.").arg(signature).arg(count); - //capturedFramesMap = map; - //for (auto key: map.keys()) - // qCDebug(KSTARS_EKOS_CAPTURE) << QString("Captured frame '%1' already has %2 captures stored.").arg(key).arg(map[key]); + // Scheduler's captured frame map overrides the progress option of the Capture module + ignoreJobProgress = false; } void Capture::setSettings(const QJsonObject &settings) diff --git a/kstars/ekos/capture/sequencejob.h b/kstars/ekos/capture/sequencejob.h --- a/kstars/ekos/capture/sequencejob.h +++ b/kstars/ekos/capture/sequencejob.h @@ -122,10 +122,11 @@ int getYBin() { return binY; } void setDelay(int in_delay) { delay = in_delay; } - void setCount(int in_count) { count = in_count; } + void setCount(int in_count); void setExposure(double duration) { exposure = duration; } - void setStatusCell(QTableWidgetItem *cell) { statusCell = cell; } - void setCompleted(int in_completed) { completed = in_completed; } + void setStatusCell(QTableWidgetItem *cell); + void setCountCell(QTableWidgetItem *cell); + void setCompleted(int in_completed); int getISOIndex() const; void setISOIndex(int value); @@ -210,6 +211,7 @@ private: bool areActionsReady(); void setAllActionsReady(); + void setStatus(JOBStatus const); QStringList statusStrings; ISD::CCDChip *activeChip { nullptr }; @@ -248,6 +250,7 @@ double currentRotation { 0 }; FITSScale captureFilter { FITS_NONE }; QTableWidgetItem *statusCell { nullptr }; + QTableWidgetItem *countCell { nullptr }; QString postCaptureScript; ISD::CCD::UploadMode uploadMode { ISD::CCD::UPLOAD_CLIENT }; diff --git a/kstars/ekos/capture/sequencejob.cpp b/kstars/ekos/capture/sequencejob.cpp --- a/kstars/ekos/capture/sequencejob.cpp +++ b/kstars/ekos/capture/sequencejob.cpp @@ -46,31 +46,24 @@ void SequenceJob::resetStatus() { - status = JOB_IDLE; - completed = 0; + setStatus(JOB_IDLE); + setCompleted(0); exposeLeft = 0; captureRetires = 0; m_JobProgressIgnored = false; - if (preview == false && statusCell) - statusCell->setText(statusStrings[status]); } void SequenceJob::abort() { - status = JOB_ABORTED; - if (preview == false && statusCell) - statusCell->setText(statusStrings[status]); + setStatus(JOB_ABORTED); if (activeChip->canAbort()) activeChip->abortExposure(); activeChip->setBatchMode(false); } void SequenceJob::done() { - status = JOB_DONE; - - if (statusCell) - statusCell->setText(statusStrings[status]); + setStatus(JOB_DONE); } void SequenceJob::prepareCapture() @@ -193,6 +186,49 @@ } } +void SequenceJob::setStatus(JOBStatus const in_status) +{ + status = in_status; + if( !preview && nullptr != statusCell) + statusCell->setText(statusStrings[in_status]); +} + +void SequenceJob::setStatusCell(QTableWidgetItem* cell) +{ + statusCell = cell; + if (nullptr != cell) + { + cell->setTextAlignment(Qt::AlignHCenter); + cell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + setStatus(getStatus()); + } +} + +void SequenceJob::setCount(int in_count) +{ + count = in_count; + if( !preview && nullptr != countCell) + countCell->setText(QString("%L1/%L2").arg(completed).arg(in_count)); +} + +void SequenceJob::setCompleted(int in_completed) +{ + completed = in_completed; + if( !preview && nullptr != countCell) + countCell->setText(QString("%L1/%L2").arg(in_completed).arg(count)); +} + +void SequenceJob::setCountCell(QTableWidgetItem* cell) +{ + countCell = cell; + if (nullptr != cell) + { + cell->setTextAlignment(Qt::AlignHCenter); + cell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + setCount(getCount()); + } +} + bool SequenceJob::getJobProgressIgnored() const { return m_JobProgressIgnored; @@ -266,21 +302,13 @@ // So setting binning first always ensures this will work. if (activeChip->canBin() && activeChip->setBinning(binX, binY) == false) { - status = JOB_ERROR; - - if (preview == false && statusCell) - statusCell->setText(statusStrings[status]); - + setStatus(JOB_ERROR); return CAPTURE_BIN_ERROR; } if ((w > 0 && h > 0) && activeChip->canSubframe() && activeChip->setFrame(x, y, w, h) == false) { - status = JOB_ERROR; - - if (preview == false && statusCell) - statusCell->setText(statusStrings[status]); - + setStatus(JOB_ERROR); return CAPTURE_FRAME_ERROR; } } @@ -298,9 +326,7 @@ activeCCD->setFilter(filter); //status = JOB_BUSY; - - if (preview == false && statusCell) - statusCell->setText(statusStrings[status]); + setStatus(getStatus()); exposeLeft = exposure; diff --git a/kstars/ekos/opsekos.ui b/kstars/ekos/opsekos.ui --- a/kstars/ekos/opsekos.ui +++ b/kstars/ekos/opsekos.ui @@ -282,6 +282,19 @@ + + + + <html><head/><body><p>When processing a scheduled job, resume the sequence starting from the last image present in storage.</p></body></html> + + + Remember Job Progress + + + false + + + @@ -398,15 +411,15 @@ - + - When loading a sequence file, resume the sequence starting from the last captured image, if any. + <html><head/><body><p>When starting to process a sequence list, reset all capture counts to zero. Scheduler overrides this option when Remember Job Progress is enabled.</p></body></html> - Remember Job Progress + Always Reset Sequence When Starting - true + false diff --git a/kstars/ekos/scheduler/scheduler.cpp b/kstars/ekos/scheduler/scheduler.cpp --- a/kstars/ekos/scheduler/scheduler.cpp +++ b/kstars/ekos/scheduler/scheduler.cpp @@ -4511,9 +4511,12 @@ break; default: + // Scheduler always sets captured frame map when starting a sequence - count may be different, robustness, dynamic priority +#if 0 // JM 2018-09-24: If job is looping, no need to set captured frame maps. if (currentJob->getCompletionCondition() != SchedulerJob::FINISH_SEQUENCE) break; +#endif // hand over the map of captured frames so that the capture // process knows about existing frames @@ -4538,11 +4541,13 @@ break; } - + // Never ignore sequence history in the Capture module, it is unrelated to storage +#if 0 // If sequence is a loop, ignore sequence history // FIXME: set, but never used. if (currentJob->getCompletionCondition() != SchedulerJob::FINISH_SEQUENCE) captureInterface->call(QDBus::AutoDetect, "ignoreSequenceHistory"); +#endif // Start capture process captureInterface->call(QDBus::AutoDetect, "start"); diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg --- a/kstars/kstars.kcfg +++ b/kstars/kstars.kcfg @@ -1591,9 +1591,9 @@ 0 - - - true + + + false @@ -2158,6 +2158,10 @@ 2 + + + true + 5