diff --git a/kstars/ekos/capture/capture.h b/kstars/ekos/capture/capture.h --- a/kstars/ekos/capture/capture.h +++ b/kstars/ekos/capture/capture.h @@ -19,6 +19,7 @@ #include "indi/indilightbox.h" #include "indi/inditelescope.h" #include "ekos/auxiliary/filtermanager.h" +#include "ekos/scheduler/schedulerjob.h" #include #include @@ -742,6 +743,6 @@ QList> DSLRInfos; // Captured Frames Map - QMap capturedFramesMap; + SchedulerJob::CapturedFramesMap capturedFramesMap; }; } 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 @@ -435,8 +435,8 @@ void Capture::stop(bool abort) { retries = 0; - seqTotalCount = 0; - seqCurrentCount = 0; + //seqTotalCount = 0; + //seqCurrentCount = 0; ADURaw.clear(); ExpRaw.clear(); @@ -532,6 +532,8 @@ //button->setEnabled(true); seqTimer->stop(); + + activeJob = nullptr; } void Capture::sendNewImage(QImage *image, ISD::CCDChip *myChip) @@ -1180,7 +1182,7 @@ KSNotification::event(QLatin1String("EkosCaptureImageReceived"), i18n("Captured image received"), KSNotification::EVENT_INFO); // If it was initially set as preview job - if (seqTotalCount <= 0) + if (activeJob->isPreview()) { jobs.removeOne(activeJob); // Reset upload mode if it was changed by preview @@ -1205,6 +1207,14 @@ return false; } + /* Increase the sequence's current capture count */ + activeJob->setCompleted(activeJob->getCompleted() + 1); + + /* If we were assigned a captured frame map, also increase the relevant counter for prepareJob */ + SchedulerJob::CapturedFramesMap::iterator frame_item = capturedFramesMap.find(activeJob->getSignature()); + if (capturedFramesMap.end() != frame_item) + frame_item.value()++; + if (activeJob->getFrameType() != FRAME_LIGHT) { if (processPostCaptureCalibrationStage() == false) @@ -1214,16 +1224,15 @@ calibrationStage = CAL_CAPTURING; } - seqCurrentCount++; - activeJob->setCompleted(seqCurrentCount); - imgProgress->setValue(seqCurrentCount); + /* The image progress has now one more capture */ + imgProgress->setValue(activeJob->getCompleted()); - appendLogText(i18n("Received image %1 out of %2.", seqCurrentCount, seqTotalCount)); + appendLogText(i18n("Received image %1 out of %2.", activeJob->getCompleted(), activeJob->getCount())); state = CAPTURE_IMAGE_RECEIVED; emit newStatus(Ekos::CAPTURE_IMAGE_RECEIVED); - currentImgCountOUT->setText(QString::number(seqCurrentCount)); + currentImgCountOUT->setText(QString::number(activeJob->getCompleted())); // Check if we need to execute post capture script first if (activeJob->getPostCaptureScript().isEmpty() == false) @@ -1234,7 +1243,7 @@ } // if we're done - if (seqCurrentCount >= seqTotalCount) + if (activeJob->getCount() <= activeJob->getCompleted()) { processJobCompletion(); return true; @@ -1298,8 +1307,8 @@ return false; } - // If seqTotalCount is zero, we have to find if there are more pending jobs in the queue - if (seqTotalCount == 0) + // If no job is active, we have to find if there are more pending jobs in the queue + if (!activeJob) { SequenceJob *next_job = nullptr; @@ -1593,7 +1602,7 @@ { case SequenceJob::CAPTURE_OK: { - appendLogText(i18n("Capturing image...")); + appendLogText(i18n("Capturing %1-second %2 image...", QString::number(activeJob->getExposure(),'g',3), activeJob->getFilterName())); if (activeJob->isPreview() == false) { int index = jobs.indexOf(activeJob); @@ -1694,7 +1703,7 @@ { int newFileIndex = -1; QString tempName; - seqFileCount = 0; + // seqFileCount = 0; // No updates during meridian flip if (meridianFlipStage >= MF_ALIGNING) @@ -1715,7 +1724,11 @@ if (tempName.startsWith(finalSeqPrefix, Qt::CaseInsensitive) == false) continue; - seqFileCount++; + /* Do not change the number of captures. + * - If the sequence is required by the end-user, unconditionally run what each sequence item is requiring. + * - If the sequence is required by the scheduler, use capturedFramesMap to determine when to stop capturing. + */ + //seqFileCount++; int lastUnderScoreIndex = tempName.lastIndexOf("_"); if (lastUnderScoreIndex > 0) @@ -2237,95 +2250,123 @@ { activeJob = job; - qCDebug(KSTARS_EKOS_CAPTURE) << "Preparing capture job" << job->getFullPrefix() << "for execution."; + qCDebug(KSTARS_EKOS_CAPTURE) << "Preparing capture job" << job->getSignature() << "for execution."; if (activeJob->getActiveCCD() != currentCCD) { setCCD(activeJob->getActiveCCD()->getDeviceName()); } - if (activeJob->isPreview()) + /*if (activeJob->isPreview()) seqTotalCount = -1; else - seqTotalCount = activeJob->getCount(); + seqTotalCount = activeJob->getCount();*/ seqDelay = activeJob->getDelay(); - seqCurrentCount = activeJob->getCompleted(); + // seqCurrentCount = activeJob->getCompleted(); if (activeJob->isPreview() == false) { - fullImgCountOUT->setText(QString::number(seqTotalCount)); - currentImgCountOUT->setText(QString::number(seqCurrentCount)); + int const completion_count = activeJob->isPreview() ? -1 : activeJob->getCompleted(); + fullImgCountOUT->setText(QString::number(activeJob->getCount())); + currentImgCountOUT->setText(QString::number(completion_count)); // set the progress info imgProgress->setEnabled(true); - imgProgress->setMaximum(seqTotalCount); - imgProgress->setValue(seqCurrentCount); + imgProgress->setMaximum(activeJob->getCount()); + imgProgress->setValue(completion_count); if (currentCCD->getUploadMode() != ISD::CCD::UPLOAD_LOCAL) updateSequencePrefix(activeJob->getFullPrefix(), activeJob->getSignature()); } - // We check if the job is already fully or partially complete by checking how many files of its type exist on the file system unless ignoreJobProgress is set to true - if (ignoreJobProgress == false && activeJob->isPreview() == false) + // We check if the job is already fully or partially complete by checking how many files of its type exist on the file system + if (activeJob->isPreview() == false) { - // The signature is the unique identification path in the system for a particular job - // e.g. /home/jasem/M45/Light_Red + // The signature is the unique identification path in the system for a particular job. Format is "///". + // If the Scheduler is requesting the Capture tab to process a sequence job, a target name will be inserted after the sequence file storage field (e.g. /path/to/storage/target/Light/...) + // If the end-user is requesting the Capture tab to process a sequence job, the sequence file storage will be used as is (e.g. /path/to/storage/Light/...) QString signature = activeJob->getSignature(); // Now check on the file system ALL the files that exist with the above signature // If 29 files exist for example, then nextSequenceID would be the NEXT file number (30) // Therefore, we know how to number the next file. + // However, we do not deduce the number of captures to process from this function. checkSeqBoundary(signature); // Captured Frames Map contains a list of signatures:count of _already_ captured files in the file system. - // This is usually set by the scheduler in case we have duplicate signatures. - // Eg. Simple Sequence = LRGB - // Scheduler wants to run job 3 times, with each sequence capture 5 frames per filter. - // When the first scheduler job is complete. On the file system, we have 20 images (5 for each filter) - // When the SECOND job scheduler starts. It already finds 20 images on the filter system, so it sets - // the signatures of L,R,G, and B to ZERO (seqFileCount) even though seqFileCount is set to 5 by the - // checkSeqBoundary function since this is what exists on the filter system for this signature. - // Therefore, we continue to capture the SECOND scheduler job without issues. - // This is the purpose of capturedFramesMap + // This map is set by the Scheduler in order to complete efficiently the required captures. + // When the end-user requests a sequence to be processed, that map is empty. + // + // Example with a 5xL-5xR-5xG-5xB sequence + // + // When the end-user loads and runs this sequence, each filter gets to capture 5 frames, then the procedure stops. + // When the Scheduler executes a job with this sequence, the procedure depends on what is in the storage. + // + // Let's consider the Scheduler has 3 instances of this job to run. + // + // When the first job completes the sequence, there are 20 images in the file system (5 for each filter). + // When the second job starts, Scheduler finds those 20 images but requires 20 more images, thus sets the frames map counters to 0 for all LRGB frames. + // When the third job starts, Scheduler now has 40 images, but still requires 20 more, thus again sets the frames map counters to 0 for all LRGB frames. + // + // Now let's consider something went wrong, and the third job was aborted before getting to 60 images, say we have full LRG, but only 1xB. + // When Scheduler attempts to run the aborted job again, it will count captures in storage, substract previous job requirements, and set the frames map counters to 0 for LRG, and 4 for B. + // When the sequence runs, the procedure will bypass LRG and proceed to capture 4xB. if (capturedFramesMap.contains(signature)) - seqFileCount = capturedFramesMap[signature]; + { + // Get the current capture count from the map + int count = capturedFramesMap[signature]; - if (seqFileCount > 0) + // Count how many captures this job has to process, given that previous jobs may have done some work already + foreach (SequenceJob *a_job, jobs) + if (a_job == activeJob) + break; + else if (a_job->getSignature() == activeJob->getSignature()) + count -= a_job->getCompleted(); + + // This is the current completion count of the current job + activeJob->setCompleted(count); + } + else { - // Get the TOTAL count of frames for a particular signature - // e.g. Suppose Sequnce is LRGBRGB each 5 frames - // getTotalFramesCount("R") = 10 - int totalSignatureFrameCount = getTotalFramesCount(signature); + // No preliminary information, we reset the job count and run the job unconditionally to clarify the behavior + activeJob->setCompleted(0); + } - // Fully complete - if (seqFileCount >= totalSignatureFrameCount) - { - activeJob->setCompleted(seqFileCount); - imgProgress->setValue(totalSignatureFrameCount); - qCDebug(KSTARS_EKOS_CAPTURE) << "Job" << job->getFullPrefix() << "already complete."; - processJobCompletion(); - return; - } + //qCDebug(KSTARS_EKOS_CAPTURE) << "Job" << activeJob->getSignature() << "has" << activeJob->getCompleted() << "captures already processed for this run."; + imgProgress->setValue(getTotalFramesCount(signature)); - // Partially complete - seqCurrentCount = seqFileCount; - activeJob->setCompleted(seqCurrentCount); - currentImgCountOUT->setText(QString::number(seqCurrentCount)); - qCDebug(KSTARS_EKOS_CAPTURE) << "Job" << job->getFullPrefix() << seqCurrentCount << "out of" << seqTotalCount << "is complete."; - imgProgress->setValue(seqCurrentCount); + // Check whether active job is complete by comparing required captures to what is already available + if (activeJob->getCount() <= activeJob->getCompleted()) + { + activeJob->setCompleted(activeJob->getCount()); + appendLogText(i18n("Job requires %1-second %2 images, has already %3/%4 captures and does not need to run.", + QString::number(job->getExposure(),'g',3), job->getFilterName(), + activeJob->getCompleted(), activeJob->getCount())); + processJobCompletion(); - // Emit progress update - emit newImage(nullptr, activeJob); + /* FIXME: find a clearer way to exit here */ + return; } + else + { + // There are captures to process + currentImgCountOUT->setText(QString::number(activeJob->getCompleted())); + appendLogText(i18n("Job requires %1-second %2 images, has %3/%4 frames captured and will be processed.", + QString::number(job->getExposure(),'g',3), job->getFilterName(), + activeJob->getCompleted(), activeJob->getCount())); - currentCCD->setNextSequenceID(nextSequenceID); + // Emit progress update - done a few lines below + // emit newImage(nullptr, activeJob); + + currentCCD->setNextSequenceID(nextSequenceID); + } } if (currentCCD->isBLOBEnabled() == false) { - + // FIXME: Move this warning pop-up elsewhere, it will interfere with automation. if (Options::guiderType() != Ekos::Guide::GUIDE_INTERNAL || KMessageBox::questionYesNo(nullptr, i18n("Image transfer is disabled for this camera. Would you like to enable it?")) == KMessageBox::Yes) { @@ -2573,8 +2614,11 @@ return; } - appendLogText(i18n("Guiding deviation %1 exceeded limit value of %2 arcsecs, aborting exposure.", - deviationText, guideDeviation->value())); + appendLogText(i18n("Guiding deviation %1 exceeded limit value of %2 arcsecs, " + "aborting exposure and waiting for guider up to %3 seconds.", + deviationText, guideDeviation->value(), + QString::number((double)guideDeviationTimer.interval()/1000.0f,'g',3))); + abort(); spikeDetected = false; @@ -2597,19 +2641,21 @@ guideDeviationTimer.stop(); if (seqDelay == 0) - appendLogText( - i18n("Guiding deviation %1 is now lower than limit value of %2 arcsecs, resuming exposure.", - deviationText, guideDeviation->value())); + appendLogText(i18n("Guiding deviation %1 is now lower than limit value of %2 arcsecs, " + "resuming exposure.", + deviationText, guideDeviation->value())); else - appendLogText(i18n("Guiding deviation %1 is now lower than limit value of %2 arcsecs, resuming " - "exposure in %3 seconds.", + appendLogText(i18n("Guiding deviation %1 is now lower than limit value of %2 arcsecs, " + "resuming exposure in %3 seconds.", deviationText, guideDeviation->value(), seqDelay / 1000.0)); activeJob = nullptr; QTimer::singleShot(seqDelay, this, SLOT(start())); return; } + else appendLogText(i18n("Guiding deviation %1 is still higher than limit value of %2 arcsecs.", + deviationText, guideDeviation->value())); } } @@ -3412,6 +3458,7 @@ stop(); ignoreJobProgress = true; + capturedFramesMap.clear(); } void Capture::ignoreSequenceHistory() @@ -3883,6 +3930,10 @@ return INVALID_VALUE; } + /* Edge case: undefined HA at poles */ + if (90.0f == currentDEC || -90.0f == currentDEC) + return INVALID_VALUE; + dms lst = KStarsData::Instance()->geo()->GSTtoLST(KStarsData::Instance()->clock()->utc().gst()); dms ha(lst.Degrees() - currentRA * 15.0); @@ -4720,10 +4771,9 @@ bool Capture::processPostCaptureCalibrationStage() { // If there are no more images to capture, do not bother calculating next exposure - if (calibrationStage == CAL_CALIBRATION_COMPLETE && (seqCurrentCount + 1) >= seqTotalCount) - { - return true; - } + if (calibrationStage == CAL_CALIBRATION_COMPLETE) + if (activeJob && activeJob->getCount() <= activeJob->getCompleted()) + return true; // Check if we need to do flat field slope calculation if the user specified a desired ADU value if (activeJob->getFrameType() == FRAME_FLAT && activeJob->getFlatFieldDuration() == DURATION_ADU && @@ -4852,21 +4902,22 @@ { appendLogText(i18n("Post capture script finished with code %1.", exitCode)); - // if we're done - // FIXME getTotalFramesCount is problematic elsewhere. Check here - if (seqCurrentCount >= getTotalFramesCount(activeJob->getSignature())) + // If we're done, proceed to completion. + if (activeJob->getCount() <= activeJob->getCompleted()) { processJobCompletion(); - return; } - - // Check if meridian condition is met - if (checkMeridianFlip()) - return; - - appendLogText(i18n("Resuming sequence...")); - // Then just resume sequence. - resumeSequence(); + // Else check if meridian condition is met. + else if (checkMeridianFlip()) + { + appendLogText(i18n("Processing meridian flip...")); + } + // Then if nothing else, just resume sequence. + else + { + appendLogText(i18n("Resuming sequence...")); + resumeSequence(); + } } // FIXME Migrate to Filter Manager @@ -5295,6 +5346,10 @@ void Capture::setCapturedFramesMap(const QString &signature, int count) { capturedFramesMap[signature] = count; + qCDebug(KSTARS_EKOS_CAPTURE) << QString("Client module indicates that storage '%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]); } 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 @@ -60,7 +60,7 @@ bool isPreview() { return preview; } int getDelay() { return delay; } int getCount() { return count; } - unsigned int getCompleted() { return completed; } + int getCompleted() { return completed; } const QString &getRawPrefix() { return rawPrefix; } double getExposure() const { return exposure; } @@ -123,7 +123,7 @@ void setCount(int in_count) { count = in_count; } void setExposure(double duration) { exposure = duration; } void setStatusCell(QTableWidgetItem *cell) { statusCell = cell; } - void setCompleted(unsigned int in_completed) { completed = in_completed; } + void setCompleted(int in_completed) { completed = in_completed; } int getISOIndex() const; void setISOIndex(int value); 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 @@ -4762,89 +4762,131 @@ void Scheduler::unParkMount() { QDBusReply const mountReply = mountInterface->call(QDBus::AutoDetect, "getParkingStatus"); - Mount::ParkingStatus status = (Mount::ParkingStatus)mountReply.value(); if (mountReply.error().type() != QDBusError::NoError) { qCCritical(KSTARS_EKOS_SCHEDULER) << QString("Warning: mount getParkingStatus request received DBUS error: %1").arg(QDBusError::errorString(mountReply.error().type())); - status = Mount::PARKING_ERROR; + parkWaitState = PARKWAIT_ERROR; } - - if (status != Mount::UNPARKING_OK) + else switch ((Mount::ParkingStatus) mountReply.value()) { - if (status == Mount::UNPARKING_BUSY) - appendLogText(i18n("Unparking mount in progress...")); - else - { - mountInterface->call(QDBus::AutoDetect, "unpark"); - appendLogText(i18n("Unparking mount...")); + case Mount::UNPARKING_OK: + if (startupState == STARTUP_UNPARK_MOUNT) + startupState = STARTUP_UNPARK_CAP; + else if (parkWaitState == PARKWAIT_UNPARK) + parkWaitState = PARKWAIT_UNPARKED; - currentOperationTime.start(); - } + appendLogText(i18n("Mount already unparked.")); + break; - if (startupState == STARTUP_UNPARK_MOUNT) - startupState = STARTUP_UNPARKING_MOUNT; - else if (parkWaitState == PARKWAIT_UNPARK) - parkWaitState = PARKWAIT_UNPARKING; - } - else - { - appendLogText(i18n("Mount already unparked.")); + case Mount::PARKING_BUSY: + /* FIXME: Handle the situation where we request unparking but a parking procedure is running. */ - if (startupState == STARTUP_UNPARK_MOUNT) - startupState = STARTUP_UNPARK_CAP; - else if (parkWaitState == PARKWAIT_UNPARK) - parkWaitState = PARKWAIT_UNPARKED; + case Mount::PARKING_IDLE: + case Mount::PARKING_OK: + case Mount::PARKING_ERROR: + { + QDBusReply const mountReply = mountInterface->call(QDBus::AutoDetect, "unpark"); + + if (mountReply.error().type() != QDBusError::NoError) + { + qCCritical(KSTARS_EKOS_SCHEDULER) << QString("Warning: mount unpark request received DBUS error: %1").arg(QDBusError::errorString(mountReply.error().type())); + parkWaitState = PARKWAIT_ERROR; + } + else currentOperationTime.start(); + } + + /* no-break */ + [[fallthrough]]; + + case Mount::UNPARKING_BUSY: + if (startupState == STARTUP_UNPARK_MOUNT) + startupState = STARTUP_UNPARKING_MOUNT; + else if (parkWaitState == PARKWAIT_UNPARK) + parkWaitState = PARKWAIT_UNPARKING; + + qCInfo(KSTARS_EKOS_SCHEDULER) << "Unparking mount in progress..."; + break; + + default: + qCWarning(KSTARS_EKOS_SCHEDULER) << QString("BUG: Parking state %1 not managed while unparking mount.").arg(mountReply.value()); } } void Scheduler::checkMountParkingStatus() { static int parkingFailureCount = 0; QDBusReply const mountReply = mountInterface->call(QDBus::AutoDetect, "getParkingStatus"); - Mount::ParkingStatus status = (Mount::ParkingStatus)mountReply.value(); if (mountReply.error().type() != QDBusError::NoError) { qCCritical(KSTARS_EKOS_SCHEDULER) << QString("Warning: mount getParkingStatus request received DBUS error: %1").arg(QDBusError::errorString(mountReply.error().type())); - status = Mount::PARKING_ERROR; + parkWaitState = PARKWAIT_ERROR; } - - switch (status) + else switch ((Mount::ParkingStatus)mountReply.value()) { case Mount::PARKING_OK: appendLogText(i18n("Mount parked.")); - if (shutdownState == SHUTDOWN_PARKING_MOUNT) + + if (startupState == STARTUP_UNPARKING_MOUNT) + startupState = STARTUP_UNPARK_CAP; + else if (shutdownState == SHUTDOWN_PARKING_MOUNT) shutdownState = SHUTDOWN_PARK_DOME; else if (parkWaitState == PARKWAIT_PARKING) parkWaitState = PARKWAIT_PARKED; + parkingFailureCount = 0; break; case Mount::UNPARKING_OK: appendLogText(i18n("Mount unparked.")); + if (startupState == STARTUP_UNPARKING_MOUNT) startupState = STARTUP_UNPARK_CAP; + else if (shutdownState == SHUTDOWN_PARKING_MOUNT) + shutdownState = SHUTDOWN_PARK_DOME; else if (parkWaitState == PARKWAIT_UNPARKING) parkWaitState = PARKWAIT_UNPARKED; + parkingFailureCount = 0; break; - case Mount::PARKING_BUSY: + // FIXME: Create an option for the parking/unparking timeout. + case Mount::UNPARKING_BUSY: - // TODO make the timeouts configurable by the user if (currentOperationTime.elapsed() > (60 * 1000)) { - if (parkingFailureCount++ < MAX_FAILURE_ATTEMPTS) + if (++parkingFailureCount < MAX_FAILURE_ATTEMPTS) { - appendLogText(i18n("Operation timeout. Restarting operation...")); - if (status == Mount::PARKING_BUSY) - parkMount(); - else - unParkMount(); - break; + appendLogText(i18n("Warning: mount unpark operation timed out on attempt %1/%2. Restarting operation...", parkingFailureCount, MAX_FAILURE_ATTEMPTS)); + unParkMount(); + } + else + { + appendLogText(i18n("Warning: mount unpark operation timed out on last attempt.")); + parkWaitState = PARKWAIT_ERROR; } } + else qCInfo(KSTARS_EKOS_SCHEDULER) << "Unparking mount in progress..."; + + break; + + case Mount::PARKING_BUSY: + if (currentOperationTime.elapsed() > (60 * 1000)) + { + if (++parkingFailureCount < MAX_FAILURE_ATTEMPTS) + { + appendLogText(i18n("Warning: mount park operation timed out on attempt %1/%2. Restarting operation...", parkingFailureCount, MAX_FAILURE_ATTEMPTS)); + parkMount(); + } + else + { + appendLogText(i18n("Warning: mount park operation timed out on last attempt.")); + parkWaitState = PARKWAIT_ERROR; + } + } + else qCInfo(KSTARS_EKOS_SCHEDULER) << "Parking mount in progress..."; + break; case Mount::PARKING_ERROR: @@ -4868,11 +4910,12 @@ appendLogText(i18n("Mount unparking error.")); parkWaitState = PARKWAIT_ERROR; } + parkingFailureCount = 0; break; default: - break; + qCWarning(KSTARS_EKOS_SCHEDULER) << QString("BUG: Parking state %1 not managed while checking progress.").arg(mountReply.value()); } } diff --git a/kstars/ekos/scheduler/schedulerjob.h b/kstars/ekos/scheduler/schedulerjob.h --- a/kstars/ekos/scheduler/schedulerjob.h +++ b/kstars/ekos/scheduler/schedulerjob.h @@ -306,8 +306,9 @@ /** @brief The map of capture counts for this job, keyed by its capture storage signatures. */ /** @{ */ - QMap getCapturedFramesMap() const { return capturedFramesMap; } - void setCapturedFramesMap(const QMap &value); + typedef QMap CapturedFramesMap; + const CapturedFramesMap& getCapturedFramesMap() const { return capturedFramesMap; } + void setCapturedFramesMap(const CapturedFramesMap &value); /** @} */ /** @brief Refresh all cells connected to this SchedulerJob. */ diff --git a/kstars/ekos/scheduler/schedulerjob.cpp b/kstars/ekos/scheduler/schedulerjob.cpp --- a/kstars/ekos/scheduler/schedulerjob.cpp +++ b/kstars/ekos/scheduler/schedulerjob.cpp @@ -307,7 +307,7 @@ updateJobCell(); } -void SchedulerJob::setCapturedFramesMap(const QMap &value) +void SchedulerJob::setCapturedFramesMap(const CapturedFramesMap &value) { capturedFramesMap = value; }