11#include "kstarsdata.h"
12#include "auxiliary/ksmessagebox.h"
13#include "ekos/manager.h"
14#include "ekos/auxiliary/darklibrary.h"
15#include "ekos/auxiliary/filtermanager.h"
16#include "ekos/auxiliary/opticaltrainmanager.h"
17#include "ekos/auxiliary/opticaltrainsettings.h"
18#include "ekos/auxiliary/profilesettings.h"
19#include "ekos/auxiliary/rotatorutils.h"
20#include "capturedeviceadaptor.h"
21#include "captureprocess.h"
22#include "sequencequeue.h"
23#include "scriptsmanager.h"
24#include "dslrinfodialog.h"
25#include "ui_dslrinfo.h"
26#include "exposurecalculator/exposurecalculatordialog.h"
28#include "indi/driverinfo.h"
29#include "indi/indirotator.h"
30#include "oal/observeradd.h"
32#include <ekos_capture_debug.h>
37#define KEY_FORMATS "formatsList"
38#define KEY_GAIN_KWD "ccdGainKeyword"
39#define KEY_OFFSET_KWD "ccdOffsetKeyword"
40#define KEY_TEMPERATURE "ccdTemperatures"
41#define KEY_TIMESTAMP "timestamp"
42#define KEY_FILTERS "filtersList"
43#define KEY_ISOS "isoList"
44#define KEY_INDEX "isoIndex"
45#define KEY_GAIN_KWD "ccdGainKeyword"
46#define KEY_OFFSET_KWD "ccdOffsetKeyword"
55 m_customPropertiesDialog.reset(
new CustomProperties());
56 m_LimitsDialog =
new QDialog(
this);
57 m_LimitsUI.reset(
new Ui::Limits());
58 m_LimitsUI->setupUi(m_LimitsDialog);
60 m_CalibrationDialog =
new QDialog(
this);
61 m_CalibrationUI.reset(
new Ui::Calibration());
62 m_CalibrationUI->setupUi(m_CalibrationDialog);
64 m_scriptsManager =
new ScriptsManager(
this);
69 auto title =
i18n(
"Capture Sequence Editor: %1", m_LimitsDialog->windowTitle());
70 m_LimitsDialog->setWindowTitle(title);
71 title =
i18n(
"Capture Sequence Editor: %1", m_scriptsManager->windowTitle());
72 m_scriptsManager->setWindowTitle(title);
76 m_DebounceTimer.setInterval(500);
77 m_DebounceTimer.setSingleShot(
true);
86 darkB->setChecked(Options::autoDark());
129 if (Options::remoteCaptureDirectory().isEmpty() ==
false)
134 if(!Options::captureDirectory().isEmpty())
145 button->setAutoDefault(
false);
151 state()->allJobs().clear();
154void Camera::initCamera()
156 KStarsData::Instance()->userdb()->GetAllDSLRInfos(state()->DSLRInfos());
157 state()->getSequenceQueue()->loadOptions();
159 if (state()->DSLRInfos().count() > 0)
165 setupOpticalTrainManager();
182 restartCamera(activeCamera()->getDeviceName());
187 static_cast<void(Camera::*)()
>(&Camera::saveSequenceQueue));
190 &Camera::selectedJobChanged);
194 resetJobEdit(m_JobUnderEdit);
219 connect(m_FilterManager.get(), &FilterManager::ready,
this, &Camera::updateCurrentFilterPosition);
224 state()->updateHFRThreshold();
225 generatePreviewFilename();
236 m_CalibrationUI->captureCalibrationParkMount->setChecked(false);
241 m_CalibrationUI->captureCalibrationWall->setChecked(false);
251 if (devices()->getActiveCamera())
253 QVariantMap auxInfo = devices()->getActiveCamera()->getDriverInfo()->getAuxInfo();
254 auxInfo[
QString(
"%1_TC").
arg(devices()->getActiveCamera()->getDeviceName())] = toggled;
255 devices()->getActiveCamera()->getDriverInfo()->setAuxInfo(auxInfo);
260 if (devices()->getActiveCamera())
265 if (devices()->getActiveCamera())
266 devices()->getActiveCamera()->setCoolerControl(
true);
270 if (devices()->getActiveCamera())
271 devices()->getActiveCamera()->setCoolerControl(
false);
281 &Camera::checkFrameType);
286 if (checked == false)
287 state()->getRefocusState()->setInSequenceFocus(false);
293 connect(m_captureModuleState.get(), &CaptureModuleState::newLimitFocusHFR,
this, [
this](
double hfr)
295 m_LimitsUI->hFRDeviation->setValue(hfr);
298 state()->getCaptureDelayTimer().setSingleShot(
true);
299 connect(&state()->getCaptureDelayTimer(), &
QTimer::timeout, m_captureProcess.get(), &CaptureProcess::captureImage);
302 state()->getCaptureTimeout().setSingleShot(
true);
304 &CaptureProcess::processCaptureTimeout);
315 customPropertiesDialog()->show();
316 customPropertiesDialog()->raise();
319 connect(customPropertiesDialog(), &CustomProperties::valueChanged,
this, [&]()
321 const double newGain = getGain();
324 const int newOffset = getOffset();
332 loadGlobalSettings();
333 connectSyncSettings();
337 updateHFRCheckAlgo();
340 updateHFRCheckAlgo();
343 updateHFRCheckAlgo();
350 generatePreviewFilename();
355 generatePreviewFilename();
359 &Camera::generatePreviewFilename);
362 generatePreviewFilename();
369 generatePreviewFilename();
373 connect(m_captureModuleState.data(), &CaptureModuleState::captureBusy,
this, &Camera::setBusy);
374 connect(m_captureModuleState.data(), &CaptureModuleState::startCapture,
this, &Camera::start);
375 connect(m_captureModuleState.data(), &CaptureModuleState::abortCapture,
this, &Camera::abort);
376 connect(m_captureModuleState.data(), &CaptureModuleState::suspendCapture,
this, &Camera::suspend);
377 connect(m_captureModuleState.data(), &CaptureModuleState::newLog,
this, &Camera::appendLogText);
378 connect(m_captureModuleState.data(), &CaptureModuleState::sequenceChanged,
this, &Camera::sequenceChanged);
379 connect(m_captureModuleState.data(), &CaptureModuleState::updatePrepareState,
this, &Camera::updatePrepareState);
380 connect(m_captureModuleState.data(), &CaptureModuleState::newFocusStatus,
this, &Camera::updateFocusStatus);
381 connect(m_captureModuleState.data(), &CaptureModuleState::runAutoFocus,
this, &Camera::runAutoFocus);
382 connect(m_captureModuleState.data(), &CaptureModuleState::resetFocus,
this, &Camera::resetFocus);
383 connect(m_captureModuleState.data(), &CaptureModuleState::adaptiveFocus,
this, &Camera::adaptiveFocus);
385 connect(m_captureProcess.data(), &CaptureProcess::sequenceChanged,
this, &Camera::sequenceChanged);
386 connect(m_captureProcess.data(), &CaptureProcess::addJob,
this, &Camera::addJob);
387 connect(m_captureProcess.data(), &CaptureProcess::newExposureProgress,
this, &Camera::newExposureProgress);
388 connect(m_captureProcess.data(), &CaptureProcess::newDownloadProgress,
this, &Camera::updateDownloadProgress);
389 connect(m_captureProcess.data(), &CaptureProcess::newImage,
this, &Camera::newImage);
390 connect(m_captureProcess.data(), &CaptureProcess::captureComplete,
this, &Camera::captureComplete);
391 connect(m_captureProcess.data(), &CaptureProcess::updateCaptureCountDown,
this, &Camera::updateCaptureCountDown);
392 connect(m_captureProcess.data(), &CaptureProcess::processingFITSfinished,
this, &Camera::processingFITSfinished);
393 connect(m_captureProcess.data(), &CaptureProcess::captureStopped,
this, &Camera::captureStopped);
394 connect(m_captureProcess.data(), &CaptureProcess::darkFrameCompleted,
this, &Camera::imageCapturingCompleted);
395 connect(m_captureProcess.data(), &CaptureProcess::syncGUIToJob,
this, &Camera::syncGUIToJob);
396 connect(m_captureProcess.data(), &CaptureProcess::refreshCameraSettings,
this, &Camera::refreshCameraSettings);
397 connect(m_captureProcess.data(), &CaptureProcess::updateFrameProperties,
this, &Camera::updateFrameProperties);
398 connect(m_captureProcess.data(), &CaptureProcess::rotatorReverseToggled,
this, &Camera::setRotatorReversed);
399 connect(m_captureProcess.data(), &CaptureProcess::refreshFilterSettings,
this, &Camera::refreshFilterSettings);
400 connect(m_captureProcess.data(), &CaptureProcess::createJob, [
this](SequenceJob::SequenceJobType jobType)
403 process()->jobCreated(createJob(jobType));
405 connect(m_captureProcess.data(), &CaptureProcess::updateJobTable,
this, &Camera::updateJobTable);
406 connect(m_captureProcess.data(), &CaptureProcess::newLog,
this, &Camera::appendLogText);
407 connect(m_captureProcess.data(), &CaptureProcess::stopCapture,
this, &Camera::stop);
408 connect(m_captureProcess.data(), &CaptureProcess::jobStarting,
this, &Camera::jobStarting);
409 connect(m_captureProcess.data(), &CaptureProcess::abortFocus,
this, &Camera::abortFocus);
410 connect(m_captureProcess.data(), &CaptureProcess::cameraReady,
this, &Camera::ready);
411 connect(m_captureProcess.data(), &CaptureProcess::captureAborted,
this, &Camera::captureAborted);
412 connect(m_captureProcess.data(), &CaptureProcess::captureRunning,
this, &Camera::captureRunning);
413 connect(m_captureProcess.data(), &CaptureProcess::captureImageStarted,
this, &Camera::captureImageStarted);
414 connect(m_captureProcess.data(), &CaptureProcess::jobExecutionPreparationStarted,
this,
415 &Camera::jobExecutionPreparationStarted);
416 connect(m_captureProcess.data(), &CaptureProcess::jobPrepared,
this, &Camera::jobPrepared);
417 connect(m_captureProcess.data(), &CaptureProcess::captureTarget,
this, &Camera::setTargetName);
418 connect(m_captureProcess.data(), &CaptureProcess::downloadingFrame,
this, [
this]()
420 captureStatusWidget->setStatus(i18n(
"Downloading..."), Qt::yellow);
424 connect(m_captureModuleState.data(), &CaptureModuleState::executeActiveJob, m_captureProcess.data(),
425 &CaptureProcess::executeJob);
426 connect(m_captureModuleState.data(), &CaptureModuleState::captureStarted, m_captureProcess.data(),
427 &CaptureProcess::captureStarted);
428 connect(m_captureModuleState.data(), &CaptureModuleState::checkFocus,
this, &Camera::checkFocus);
431 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newCCDTemperatureValue,
this,
433 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::CameraConnected,
this, [
this](
bool connected)
435 CaptureSettingsGroup->setEnabled(connected);
436 fileSettingsGroup->setEnabled(connected);
437 sequenceBox->setEnabled(connected);
438 for (auto &oneChild : sequenceControlsButtonGroup->buttons())
439 oneChild->setEnabled(connected);
442 trainLayout->setEnabled(true);
444 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::FilterWheelConnected,
this, [
this](
bool connected)
446 FilterPosLabel->setEnabled(connected);
447 FilterPosCombo->setEnabled(connected);
448 filterManagerB->setEnabled(connected);
450 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newRotator,
this, &Camera::setRotator);
451 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newRotatorAngle,
this, &Camera::updateRotatorAngle,
453 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newFilterWheel,
this, &Camera::setFilterWheel);
456 connect(m_captureModuleState.data(), &CaptureModuleState::newFilterPosition,
457 m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::setFilterPosition);
458 connect(m_captureModuleState.data(), &CaptureModuleState::abortFastExposure,
459 m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::abortFastExposure);
462void Camera::updateRotatorAngle(
double value)
464 IPState
RState = devices()->rotator()->absoluteAngleState();
466 m_RotatorControlPanel->updateRotator(value);
468 m_RotatorControlPanel->updateGauge(value);
471void Camera::setRotatorReversed(
bool toggled)
473 m_RotatorControlPanel->reverseDirection->setEnabled(
true);
474 m_RotatorControlPanel->reverseDirection->blockSignals(
true);
475 m_RotatorControlPanel->reverseDirection->setChecked(toggled);
476 m_RotatorControlPanel->reverseDirection->blockSignals(
false);
479void Camera::updateCCDTemperature(
double value)
483 if (devices()->getActiveCamera()->getPermission(
"CCD_TEMPERATURE") !=
IP_RO)
484 process()->checkCamera();
493void Camera::setFocusStatus(FocusState
newstate)
496 state()->updateFocusState(
newstate);
499void Camera::updateFocusStatus(FocusState
newstate)
501 if ((state()->getRefocusState()->isRefocusing()
502 || state()->getRefocusState()->isInSequenceFocus()) && activeJob()
503 && activeJob()->getStatus() == JOB_BUSY)
508 appendLogText(
i18n(
"Focus complete."));
522bool Camera::updateCamera()
524 auto isConnected = activeCamera() && activeCamera()->isConnected();
531 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
533 if (activeCamera() && trainID.
isValid())
535 auto name = activeCamera()->getDeviceName();
541 if (devices()->filterWheel())
542 process()->updateFilterInfo();
544 process()->checkCamera();
545 emit settingsUpdated(getAllSettings());
550void Camera::refreshCameraSettings()
554 auto camera = activeCamera();
555 auto targetChip = devices()->getActiveChip();
557 if (!m_standAlone && (!camera || !targetChip || !targetChip->getCCD() || targetChip->isCapturing()))
563 if (camera->hasCoolerControl())
567 coolerOnB->setChecked(camera->isCoolerOn());
568 coolerOffB->setChecked(!camera->isCoolerOn());
578 updateFrameProperties();
580 updateCaptureFormats();
582 customPropertiesDialog()->setCCD(camera);
584 liveVideoB->setEnabled(camera->hasVideoStream());
585 if (camera->hasVideoStream())
586 setVideoStreamEnabled(camera->isStreamingEnabled());
594 connect(camera, &ISD::Camera::error, m_captureProcess.data(), &CaptureProcess::processCaptureError,
602 DarkLibrary::Instance()->checkCamera();
605void Camera::processCameraNumber(INDI::Property
prop)
607 if (devices()->getActiveCamera() ==
nullptr)
610 if ((
prop.isNameMatch(
"CCD_FRAME") && state()->useGuideHead() ==
false) ||
611 (
prop.isNameMatch(
"GUIDER_FRAME") && state()->useGuideHead()))
612 updateFrameProperties();
613 else if ((
prop.isNameMatch(
"CCD_INFO") && state()->useGuideHead() ==
false) ||
614 (
prop.isNameMatch(
"GUIDER_INFO") && state()->useGuideHead()))
615 updateFrameProperties(1);
616 else if (
prop.isNameMatch(
"CCD_TRANSFER_FORMAT") ||
prop.isNameMatch(
"CCD_CAPTURE_FORMAT"))
617 updateCaptureFormats();
618 else if (
prop.isNameMatch(
"CCD_CONTROLS"))
621 auto gain =
nvp->findWidgetByName(
"Gain");
624 auto offset =
nvp->findWidgetByName(
"Offset");
628 else if (
prop.isNameMatch(
"CCD_GAIN"))
633 else if (
prop.isNameMatch(
"CCD_OFFSET"))
641void Camera::updateTargetDistance(
double targetDiff)
659 return CCDFrameTypeNames[
type];
665 return CCDFrameTypeNames[
type];
667 return QString(
"%1 %2").
arg(filter).
arg(CCDFrameTypeNames[type]);
673 return CCDFrameTypeNames[
type];
678void Camera::captureRunning()
680 emit captureStarting(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(),
681 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString());
682 if (isActiveJobPreview())
686 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()))
687 .arg(activeJob()->getCompleted()).arg(activeJob()->getCoreProperty(
688 SequenceJob::SJ_Count).toInt()));
698 if (state()->isLooping() ==
false && activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
699 appendLogText(
i18n(
"Capturing %1-second %2 image...",
700 QString(
"%L1").arg(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f', 3),
701 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()));
704void Camera::captureImageStarted()
706 if (devices()->filterWheel() !=
nullptr)
710 process()->updateFilterInfo();
711 updateCurrentFilterPosition();
715 if (activeJob()->getCalibrationStage() == SequenceJobState::CAL_CALIBRATION)
719void Camera::jobExecutionPreparationStarted()
721 if (activeJob() ==
nullptr)
727 if (activeJob()->jobType() == SequenceJob::JOBTYPE_PREVIEW)
728 updateStartButtons(
true,
false);
733 int index = state()->allJobs().indexOf(job);
737 if (activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
741 imgProgress->setMaximum(activeJob()->getCoreProperty(SequenceJob::SJ_Count).toInt());
742 imgProgress->setValue(activeJob()->getCompleted());
746void Camera::setTargetName(
const QString &newTargetName)
749 if (activeJob() ==
nullptr)
753 auto rows =
queueTable->selectionModel()->selectedRows();
757 int pos = rows.constFirst().row();
759 if (state()->allJobs().size() > pos)
760 state()->allJobs().at(pos)->setCoreProperty(SequenceJob::SJ_TargetName, newTargetName);
763 emit captureTarget(newTargetName);
767void Camera::jobStarting()
769 if (m_LimitsUI->enforceAutofocusHFR->isChecked() && state()->getRefocusState()->isAutoFocusReady() ==
false)
770 appendLogText(
i18n(
"Warning: in-sequence focusing is selected but autofocus process was not started."));
771 if (m_LimitsUI->enforceAutofocusOnTemperature->isChecked()
772 && state()->getRefocusState()->isAutoFocusReady() ==
false)
773 appendLogText(
i18n(
"Warning: temperature delta check is selected but autofocus process was not started."));
775 updateStartButtons(
true,
false);
779void Camera::capturePreview()
781 process()->capturePreview();
784void Camera::startFraming()
786 process()->capturePreview(
true);
789void Camera::generateDarkFlats()
796 if (state()->allJobs().at(i)->getFrameType() != FRAME_FLAT)
799 syncGUIToJob(state()->allJobs().at(i));
802 createJob(SequenceJob::JOBTYPE_DARKFLAT);
808 appendLogText(
i18np(
"One dark flats job was created.",
"%1 dark flats jobs were created.",
jobsAdded));
818void Camera::updateCaptureCountDown(
int deltaMillis)
823 if (!isActiveJobPreview())
832 createNewJobTableRow(job);
835void Camera::editJobFinished()
841 SequenceJob *job = state()->allJobs().at(currentRow);
842 updateJobFromUI(job);
845 updateJobTable(job,
true);
849 state()->getSequence().replace(currentRow,
jsonJob);
850 emit sequenceChanged(state()->getSequence());
853 appendLogText(
i18n(
"Job #%1 changes applied.", currentRow + 1));
856void Camera::imageCapturingCompleted()
864 if (state()->isLooping())
872 if (devices()->getActiveCamera()->isFastExposureEnabled() ==
false)
873 DarkLibrary::Instance()->disconnect(
this);
876 if (
thejob->getCoreProperty(SequenceJob::SJ_Exposure).toDouble() >= 1)
877 KSNotification::event(
QLatin1String(
"EkosCaptureImageReceived"),
i18n(
"Captured image received"),
878 KSNotification::Capture);
881 if (
thejob->jobType() == SequenceJob::JOBTYPE_PREVIEW)
888void Camera::captureStopped()
900 updateStartButtons(
false,
false);
903void Camera::processingFITSfinished(
bool success)
906 if (success ==
false)
910 if (devices()->getActiveCamera()
911 && devices()->getActiveCamera()->getUploadMode() != ISD::Camera::UPLOAD_LOCAL)
914 imageCapturingCompleted();
917void Camera::checkFrameType(
int index)
923void Camera::updateStartButtons(
bool start,
bool pause)
935 startB->setToolTip(
i18n(pause ?
"Resume Sequence" :
"Start Sequence"));
937 pauseB->setEnabled(start && !pause);
940void Camera::setBusy(
bool enable)
943 loopB->setEnabled(!enable);
945 trainB->setEnabled(!enable);
952void Camera::updatePrepareState(CaptureState prepareState)
954 state()->setCaptureState(prepareState);
956 if (activeJob() ==
nullptr)
963 switch (prepareState)
966 appendLogText(
i18n(
"Setting temperature to %1 °C...", activeJob()->getTargetTemperature()));
971 appendLogText(
i18n(
"Waiting for guide drift below %1\"...", Options::startGuideDeviation()));
976 appendLogText(
i18n(
"Setting camera to %1 degrees E of N...", activeJob()->getTargetRotation()));
1002 state()->allJobs().append(job);
1005 createNewJobTableRow(job);
1010bool Camera::removeJob(
int index)
1012 if (state()->getCaptureState() != CAPTURE_IDLE && state()->getCaptureState() != CAPTURE_ABORTED
1013 && state()->getCaptureState() != CAPTURE_COMPLETE)
1031 if (state()->allJobs().empty())
1036 state()->removeCapturedFrameCount(job->getSignature(), job->getCompleted());
1038 state()->allJobs().removeOne(job);
1039 if (job == activeJob())
1040 state()->setActiveJob(
nullptr);
1062 resetB->setEnabled(
false);
1065 state()->setDirty(
true);
1070void Camera::loadSequenceQueue()
1074 "Ekos Sequence Queue (*.esq)");
1078 if (
fileURL.isValid() ==
false)
1081 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1087 loadSequenceQueue(
fileURL.toLocalFile());
1090void Camera::saveSequenceQueue()
1094 if (state()->sequenceURL().toLocalFile().startsWith(
QLatin1String(
"/tmp/"))
1095 || state()->sequenceURL().toLocalFile().contains(
"/Temp"))
1096 state()->setSequenceURL(
QUrl(
""));
1099 if (state()->dirty() ==
false && !state()->sequenceURL().isEmpty())
1102 if (state()->sequenceURL().isEmpty())
1105 "Save Ekos Sequence Queue"),
1107 "Ekos Sequence Queue (*.esq)"));
1109 if (state()->sequenceURL().isEmpty())
1117 if (state()->sequenceURL().toLocalFile().endsWith(
QLatin1String(
".esq")) ==
false)
1118 state()->setSequenceURL(
QUrl(
"file:" + state()->sequenceURL().toLocalFile() +
".esq"));
1122 if (state()->sequenceURL().
isValid())
1125 if ((process()->saveSequenceQueue(state()->sequenceURL().toLocalFile(), !m_standAlone)) ==
false)
1127 KSNotification::error(
i18n(
"Failed to save sequence queue"),
i18n(
"Save"));
1131 state()->setDirty(
false);
1135 QString message =
i18n(
"Invalid URL: %1", state()->sequenceURL().url());
1136 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1141void Camera::saveSequenceQueueAs()
1143 state()->setSequenceURL(
QUrl(
""));
1144 saveSequenceQueue();
1152 while (iter.hasNext())
1153 updateJobTable(iter.next(),
full);
1158 int row = state()->allJobs().indexOf(job);
1161 updateRowStyle(job);
1164 status->setText(job->getStatusString());
1165 updateJobTableCountCell(job, count);
1169 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
1172 if (
FilterPosCombo->findText(job->getCoreProperty(SequenceJob::SJ_Filter).toString()) >= 0 &&
1175 filter->setText(job->getCoreProperty(SequenceJob::SJ_Filter).toString());
1180 exp->setText(
QString(
"%L1").arg(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f',
1184 type->setText(isDarkFlat ?
i18n(
"Dark Flat") : CCDFrameTypeNames[job->getFrameType()]);
1187 QPoint binning = job->getCoreProperty(SequenceJob::SJ_Binning).toPoint();
1191 if (job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt() != -1)
1192 iso->
setText(
captureISOS->itemText(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt()));
1193 else if (job->getCoreProperty(SequenceJob::SJ_Gain).toDouble() >= 0)
1199 if (job->getCoreProperty(SequenceJob::SJ_Offset).toDouble() >= 0)
1210 resetB->setEnabled(
true);
1211 state()->setDirty(
true);
1225 job->setCoreProperty(SequenceJob::SJ_Format,
captureFormatS->currentText());
1226 job->setCoreProperty(SequenceJob::SJ_Encoding,
captureEncodingS->currentText());
1231 job->setCoreProperty(SequenceJob::SJ_Gain, getGain());
1232 job->setCoreProperty(SequenceJob::SJ_Offset, getOffset());
1236 job->setCoreProperty(SequenceJob::SJ_EnforceTemperature,
cameraTemperatureS->isChecked());
1240 job->setScripts(m_scriptsManager->getScripts());
1241 job->setUploadMode(
static_cast<ISD::Camera::UploadMode
>(
fileUploadModeS->currentIndex()));
1244 job->setFlatFieldDuration(m_CalibrationUI->captureCalibrationDurationManual->isChecked() ? DURATION_MANUAL :
1247 int action = ACTION_NONE;
1248 if (m_CalibrationUI->captureCalibrationParkMount->isChecked())
1249 action |= ACTION_PARK_MOUNT;
1250 if (m_CalibrationUI->captureCalibrationParkDome->isChecked())
1251 action |= ACTION_PARK_DOME;
1252 if (m_CalibrationUI->captureCalibrationWall->isChecked())
1255 auto wallAz = m_CalibrationUI->azBox->createDms(&
azOk);
1256 auto wallAlt = m_CalibrationUI->altBox->createDms(&
altOk);
1260 action = (action & ~ACTION_PARK_MOUNT) | ACTION_WALL;
1268 if (m_CalibrationUI->captureCalibrationUseADU->isChecked())
1270 job->setCoreProperty(SequenceJob::SJ_TargetADU, m_CalibrationUI->captureCalibrationADUValue->value());
1271 job->setCoreProperty(SequenceJob::SJ_TargetADUTolerance,
1272 m_CalibrationUI->captureCalibrationADUTolerance->value());
1273 job->setCoreProperty(SequenceJob::SJ_SkyFlat, m_CalibrationUI->captureCalibrationSkyFlats->isChecked());
1276 job->setCalibrationPreAction(action);
1278 job->setFrameType(
static_cast<CCDFrameType
>(
qMax(0,
captureTypeS->currentIndex())));
1280 if (
FilterPosCombo->currentIndex() != -1 && (m_standAlone || devices()->filterWheel() !=
nullptr))
1285 job->setCoreProperty(SequenceJob::SJ_Count,
captureCountN->value());
1290 job->setCoreProperty(SequenceJob::SJ_Delay,
captureDelayN->value() * 1000);
1293 job->setCustomProperties(customPropertiesDialog()->getCustomProperties());
1298 job->setCoreProperty(SequenceJob::SJ_RemoteDirectory,
fileRemoteDirT->text());
1299 job->setCoreProperty(SequenceJob::SJ_LocalDirectory,
fileDirectoryT->text());
1300 job->setCoreProperty(SequenceJob::SJ_TargetName,
targetNameT->text());
1302 job->setCoreProperty(SequenceJob::SJ_PlaceholderSuffix,
formatSuffixN->value());
1304 job->setCoreProperty(SequenceJob::SJ_DitherPerJobFrequency, m_LimitsUI->guideDitherPerJobFrequency->value());
1306 auto placeholderPath = PlaceholderPath();
1309 QString signature = placeholderPath.generateSequenceFilename(*job,
1311 ".fits",
"",
false,
true);
1312 job->setCoreProperty(SequenceJob::SJ_Signature, signature);
1325 const auto roi = job->getCoreProperty(SequenceJob::SJ_ROI).toRect();
1327 captureFormatS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Format).toString());
1328 captureEncodingS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Encoding).toString());
1329 captureExposureN->setValue(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble());
1330 captureBinHN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().x());
1331 captureBinVN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().y());
1338 captureCountN->setValue(job->getCoreProperty(SequenceJob::SJ_Count).toInt());
1339 captureDelayN->setValue(job->getCoreProperty(SequenceJob::SJ_Delay).toInt() / 1000);
1340 targetNameT->setText(job->getCoreProperty(SequenceJob::SJ_TargetName).toString());
1341 fileDirectoryT->setText(job->getCoreProperty(SequenceJob::SJ_LocalDirectory).toString());
1344 fileRemoteDirT->setText(job->getCoreProperty(SequenceJob::SJ_RemoteDirectory).toString());
1345 placeholderFormatT->setText(job->getCoreProperty(SequenceJob::SJ_PlaceholderFormat).toString());
1346 formatSuffixN->setValue(job->getCoreProperty(SequenceJob::SJ_PlaceholderSuffix).toUInt());
1349 cameraTemperatureS->setChecked(job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool());
1350 if (job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool())
1354 m_LimitsUI->guideDitherPerJobFrequency->setValue(job->getCoreProperty(
1355 SequenceJob::SJ_DitherPerJobFrequency).toInt());
1356 syncLimitSettings();
1359 calibrationB->setEnabled(job->getFrameType() != FRAME_LIGHT);
1362 if (job->getFlatFieldDuration() == DURATION_MANUAL)
1363 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1365 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1368 const auto action = job->getCalibrationPreAction();
1369 if (action & ACTION_WALL)
1371 m_CalibrationUI->azBox->setText(job->getWallCoord().az().toDMSString());
1372 m_CalibrationUI->altBox->setText(job->getWallCoord().alt().toDMSString());
1374 m_CalibrationUI->captureCalibrationWall->setChecked(action & ACTION_WALL);
1375 m_CalibrationUI->captureCalibrationParkMount->setChecked(action & ACTION_PARK_MOUNT);
1376 m_CalibrationUI->captureCalibrationParkDome->setChecked(action & ACTION_PARK_DOME);
1379 switch (job->getFlatFieldDuration())
1381 case DURATION_MANUAL:
1382 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1386 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1387 m_CalibrationUI->captureCalibrationADUValue->setValue(job->getCoreProperty(SequenceJob::SJ_TargetADU).toUInt());
1388 m_CalibrationUI->captureCalibrationADUTolerance->setValue(job->getCoreProperty(
1389 SequenceJob::SJ_TargetADUTolerance).toUInt());
1390 m_CalibrationUI->captureCalibrationSkyFlats->setChecked(job->getCoreProperty(SequenceJob::SJ_SkyFlat).toBool());
1394 m_scriptsManager->setScripts(job->getScripts());
1397 customPropertiesDialog()->setCustomProperties(job->getCustomProperties());
1400 captureISOS->setCurrentIndex(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt());
1402 double gain = getGain();
1408 double offset = getOffset();
1415 generatePreviewFilename();
1417 if (m_RotatorControlPanel)
1419 if (job->getTargetRotation() != Ekos::INVALID_VALUE)
1422 m_RotatorControlPanel->setCameraPA(job->getTargetRotation());
1430 if (Options::alignCheckFrequency() == 0)
1438void Camera::syncFrameType(
const QString &name)
1440 if (!activeCamera() || name != activeCamera()->getDeviceName())
1458void Camera::syncCameraInfo()
1460 if (!activeCamera())
1463 const QString timestamp = KStarsData::Instance()->lt().toString(
"yyyy-MM-dd hh:mm");
1464 storeTrainKeyString(KEY_TIMESTAMP, timestamp);
1466 if (activeCamera()->hasCooler())
1471 if (activeCamera()->getPermission(
"CCD_TEMPERATURE") !=
IP_RO)
1473 double min, max, step;
1478 activeCamera()->getMinMaxStep(
"CCD_TEMPERATURE",
"CCD_TEMPERATURE_VALUE", &min, &max, &step);
1482 bool isChecked = activeCamera()->getDriverInfo()->getAuxInfo().value(
QString(
"%1_TC").arg(activeCamera()->getDeviceName()),
1490 isChecked ?
"1" :
"0" } );
1506 double temperature = 0;
1507 if (activeCamera()->getTemperature(&temperature))
1524 auto isoList = devices()->getActiveChip()->getISOList();
1533 if (settings().contains(KEY_ISOS))
1535 settings().remove(KEY_ISOS);
1536 m_DebounceTimer.start();
1538 if (settings().contains(KEY_INDEX))
1540 settings().remove(KEY_INDEX);
1541 m_DebounceTimer.start();
1548 const int isoIndex = devices()->getActiveChip()->getISOIndex();
1552 storeTrainKey(KEY_ISOS,
isoList);
1557 double pixelX = 0, pixelY = 0;
1558 bool rc = devices()->getActiveChip()->getImageInfo(w, h, pixelX, pixelY,
bbp);
1559 bool isModelInDB = state()->isModelinDSLRInfo(
QString(activeCamera()->getDeviceName()));
1562 if (
rc ==
true && (pixelX == 0.0 || pixelY == 0.0 ||
isModelInDB ==
false))
1573 process()->syncDSLRToTargetChip(model);
1580 if (activeCamera()->hasGain())
1583 activeCamera()->getGainMinMaxStep(&min, &max, &step);
1586 GainSpinSpecialValue = min - step;
1591 activeCamera()->getGain(&value);
1620 if (activeCamera()->hasOffset())
1623 activeCamera()->getOffsetMinMaxStep(&min, &max, &step);
1626 OffsetSpinSpecialValue = min - step;
1631 activeCamera()->getOffset(&value);
1660void Camera::createNewJobTableRow(
SequenceJob *job)
1709 updateJobTable(job,
true);
1713 state()->getSequence().append(
jsonJob);
1714 emit sequenceChanged(state()->getSequence());
1725 int row = state()->allJobs().indexOf(job);
1741 if (cell ==
nullptr)
1745 font.setBold(active);
1746 font.setItalic(active);
1750bool Camera::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget *widget)
1763 const int value = settings[key].toInt(&ok);
1766 pSB->setValue(value);
1772 const double value = settings[key].toDouble(&ok);
1775 pDSB->setValue(value);
1796 const bool value = settings[key].toBool();
1797 if (value !=
pCB->isChecked())
1803 const bool value = settings[key].toBool();
1811 const QString value = settings[key].toString();
1823 const bool value = settings[key].toBool();
1830 const auto value = settings[key].toString();
1834 generatePreviewFilename();
1841void Camera::moveJob(
bool up)
1851 for (
int i = 0; i < columnCount; i++)
1860 SequenceJob * job = state()->allJobs().takeAt(currentRow);
1862 state()->allJobs().removeOne(job);
1873 state()->setDirty(
true);
1876void Camera::removeJobFromQueue()
1883 removeJob(currentRow);
1895void Camera::saveFITSDirectory()
1898 m_dirPath.toLocalFile());
1905void Camera::updateCaptureFormats()
1917 captureTypeS->setCurrentIndex(devices()->getActiveChip()->getFrameType());
1923 const auto list = activeCamera()->getCaptureFormats();
1925 storeTrainKey(KEY_FORMATS, list);
1927 captureFormatS->setCurrentText(activeCamera()->getCaptureFormat());
1938void Camera::updateHFRCheckAlgo()
1941 const bool threshold = (m_LimitsUI->hFRCheckAlgorithm->currentIndex() != HFR_CHECK_FIXED);
1942 m_LimitsUI->hFRThresholdPercentage->setEnabled(threshold);
1943 m_LimitsUI->limitFocusHFRThresholdLabel->setEnabled(threshold);
1944 m_LimitsUI->limitFocusHFRPercentLabel->setEnabled(threshold);
1945 state()->updateHFRThreshold();
1948void Camera::clearAutoFocusHFR()
1950 if (Options::hFRCheckAlgorithm() == HFR_CHECK_FIXED)
1953 m_LimitsUI->hFRDeviation->setValue(0);
1963void Camera::clearCameraConfiguration()
1968 KSMessageBox::Instance()->disconnect(
this);
1969 devices()->getActiveCamera()->setConfig(PURGE_CONFIG);
1970 KStarsData::Instance()->userdb()->DeleteDSLRInfo(devices()->getActiveCamera()->getDeviceName());
1976 if (
shutterfulCCDs.contains(devices()->getActiveCamera()->getDeviceName()))
1978 shutterfulCCDs.removeOne(devices()->getActiveCamera()->getDeviceName());
1981 if (
shutterlessCCDs.contains(devices()->getActiveCamera()->getDeviceName()))
1983 shutterlessCCDs.removeOne(devices()->getActiveCamera()->getDeviceName());
1994 KSMessageBox::Instance()->questionYesNo(
i18n(
"Reset %1 configuration to default?",
1995 devices()->getActiveCamera()->getDeviceName()),
1996 i18n(
"Confirmation"), 30);
1999void Camera::editFilterName()
2007 if (editFilterNameInternal(labels,
newLabels))
2015 if (devices()->filterWheel() ==
nullptr || state()->getCurrentFilterPosition() < 1)
2018 QStringList labels = filterManager()->getFilterLabels();
2020 if (editFilterNameInternal(labels,
newLabels))
2021 filterManager()->setFilterNames(
newLabels);
2032 for (uint8_t i = 0; i < labels.
count(); i++)
2040 QString title = m_standAlone ?
2041 "Edit Filter Names" : devices()->filterWheel()->getDeviceName();
2052 for (uint8_t i = 0; i < labels.
count(); i++)
2060void Camera::loadGlobalSettings()
2065 QVariantMap settings;
2069 if (
oneWidget->objectName() ==
"opticalTrainCombo")
2073 value = Options::self()->property(key.
toLatin1());
2077 settings[key] = value;
2087 value = Options::self()->property(key.
toLatin1());
2091 settings[key] = value;
2101 value = Options::self()->property(key.
toLatin1());
2105 settings[key] = value;
2115 value = Options::self()->property(key.
toLatin1());
2119 settings[key] = value;
2131 value = Options::self()->property(key.
toLatin1());
2135 settings[key] = value;
2146 value = Options::self()->property(key.
toLatin1());
2150 settings[key] = value;
2160 value = Options::self()->property(key.
toLatin1());
2164 settings[key] = value;
2167 m_GlobalSettings = settings;
2168 setSettings(settings);
2179 KSNotification::error(
i18n(
"You must set remote directory for Local & Both modes."));
2185 KSNotification::error(
i18n(
"You must set local directory for Client & Both modes."));
2198 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
2210void Camera::generatePreviewFilename()
2212 if (state()->isCaptureRunning() ==
false)
2218 fileRemoteDirT->setToolTip(previewFilename( Camera::REMOTE_PREVIEW ));
2244 else if (state()->sequenceURL().toLocalFile().isEmpty() && m_format.
contains(
"%f"))
2245 previewText = (
"Save the sequence file to show filename preview");
2250 if (
m_job ==
nullptr)
2254 if (state()->sequenceURL().toLocalFile().isEmpty())
2260 previewSeq = state()->sequenceURL().toLocalFile();
2265 extension =
".fits";
2267 extension =
".xisf";
2269 extension =
".[NATIVE]";
2271 extension,
"",
false);
2274 m_job->deleteLater();
2279 previewText.
replace(separator,
"/");
2286 countCell->setText(
QString(
"%L1/%L2").arg(job->getCompleted()).
arg(job->getCoreProperty(SequenceJob::SJ_Count).toInt()));
2292 auto pos = std::find_if(state()->DSLRInfos().
begin(), state()->DSLRInfos().
end(), [model](
const auto &
oneDSLRInfo)
2297 if (pos != state()->DSLRInfos().
end())
2299 KStarsData::Instance()->userdb()->DeleteDSLRInfo(model);
2300 state()->DSLRInfos().removeOne(*pos);
2310 KStarsData::Instance()->userdb()->AddDSLRInfo(
oneDSLRInfo);
2311 KStarsData::Instance()->userdb()->GetAllDSLRInfos(state()->DSLRInfos());
2313 updateFrameProperties();
2314 process()->resetFrame();
2315 process()->syncDSLRToTargetChip(model);
2318 if (m_DSLRInfoDialog)
2319 m_DSLRInfoDialog.reset();
2324 process()->startNextPendingJob();
2327void Camera::stop(CaptureState targetState)
2329 process()->stopCapturing(targetState);
2334 process()->pauseCapturing();
2335 updateStartButtons(
false,
true);
2338void Camera::toggleSequence()
2340 const CaptureState
capturestate = state()->getCaptureState();
2342 updateStartButtons(
true,
false);
2344 process()->toggleSequence();
2347void Camera::toggleVideo(
bool enabled)
2349 process()->toggleVideo(enabled);
2352void Camera::restartCamera(
const QString &name)
2354 process()->restartCamera(name);
2357void Camera::cullToDSLRLimits()
2359 QString model(devices()->getActiveCamera()->getDeviceName());
2362 auto pos = std::find_if(state()->DSLRInfos().
begin(),
2368 if (pos != state()->DSLRInfos().
end())
2384void Camera::resetFrameToZero()
2403void Camera::updateFrameProperties(
int reset)
2405 if (!devices()->getActiveCamera())
2409 double min, max, step;
2415 QString(
"CCD_EXPOSURE_VALUE");
2416 devices()->setActiveChip(state()->useGuideHead() ?
2417 devices()->getActiveCamera()->getChip(
2418 ISD::CameraChip::GUIDE_CCD) :
2419 devices()->getActiveCamera()->getChip(
ISD::CameraChip::PRIMARY_CCD));
2421 captureFrameWN->setEnabled(devices()->getActiveChip()->canSubframe());
2422 captureFrameHN->setEnabled(devices()->getActiveChip()->canSubframe());
2423 captureFrameXN->setEnabled(devices()->getActiveChip()->canSubframe());
2424 captureFrameYN->setEnabled(devices()->getActiveChip()->canSubframe());
2426 captureBinHN->setEnabled(devices()->getActiveChip()->canBin());
2427 captureBinVN->setEnabled(devices()->getActiveChip()->canBin());
2430 exposureValues << 0.01 << 0.02 << 0.05 << 0.1 << 0.2 << 0.25 << 0.5 << 1 << 1.5 << 2 << 2.5 << 3 << 5 << 6 << 7 << 8 << 9 <<
2431 10 << 20 << 30 << 40 << 50 << 60 << 120 << 180 << 300 << 600 << 900 << 1200 << 1800;
2456 if (devices()->getActiveCamera()->getMinMaxStep(
frameProp,
"WIDTH", &min, &max, &step))
2465 xstep =
static_cast<int>(max * 0.05);
2467 xstep =
static_cast<int>(step);
2469 if (min >= 0 && max > 0)
2479 if (devices()->getActiveCamera()->getMinMaxStep(
frameProp,
"HEIGHT", &min, &max, &step))
2488 ystep =
static_cast<int>(max * 0.05);
2490 ystep =
static_cast<int>(step);
2492 if (min >= 0 && max > 0)
2502 if (devices()->getActiveCamera()->getMinMaxStep(
frameProp,
"X", &min, &max, &step))
2513 if (min >= 0 && max > 0)
2523 if (devices()->getActiveCamera()->getMinMaxStep(
frameProp,
"Y", &min, &max, &step))
2534 if (min >= 0 && max > 0)
2545 if (state()->useGuideHead() ==
false)
2548 const QString ccdGainKeyword = devices()->getActiveCamera()->getProperty(
"CCD_GAIN") ?
"CCD_GAIN" :
"CCD_CONTROLS";
2551 const QString ccdOffsetKeyword = devices()->getActiveCamera()->getProperty(
"CCD_OFFSET") ?
"CCD_OFFSET" :
"CCD_CONTROLS";
2554 if (reset == 1 || state()->frameSettings().contains(devices()->getActiveChip()) ==
false)
2556 QVariantMap settings;
2565 state()->frameSettings()[devices()->getActiveChip()] = settings;
2567 else if (reset == 2 && state()->frameSettings().contains(devices()->getActiveChip()))
2569 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2572 x = settings[
"x"].toInt();
2573 y = settings[
"y"].toInt();
2574 w = settings[
"w"].toInt();
2575 h = settings[
"h"].toInt();
2590 state()->frameSettings()[devices()->getActiveChip()] = settings;
2593 if (state()->frameSettings().contains(devices()->getActiveChip()))
2595 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2596 int x = settings[
"x"].toInt();
2597 int y = settings[
"y"].toInt();
2598 int w = settings[
"w"].toInt();
2599 int h = settings[
"h"].toInt();
2601 if (devices()->getActiveChip()->canBin())
2603 devices()->getActiveChip()->getMaxBin(&
binx, &
biny);
2627void Camera::setGain(
double value)
2631 setStandAloneGain(value);
2634 if (!devices()->getActiveCamera())
2639 customPropertiesDialog()->setCustomProperties(
customProps);
2643double Camera::getGain()
2645 return devices()->cameraGain(customPropertiesDialog()->getCustomProperties());
2648void Camera::setOffset(
double value)
2652 setStandAloneOffset(value);
2655 if (!devices()->getActiveCamera())
2661 customPropertiesDialog()->setCustomProperties(
customProps);
2664double Camera::getOffset()
2666 return devices()->cameraOffset(customPropertiesDialog()->getCustomProperties());
2669void Camera::setRotator(
QString name)
2674 if (Rotator && !m_RotatorControlPanel.isNull())
2675 m_RotatorControlPanel->close();
2680 Manager::Instance()->getRotatorController(name, m_RotatorControlPanel);
2681 m_RotatorControlPanel->initRotator(
opticalTrainCombo->currentText(), devices().data(),
2685 m_RotatorControlPanel->show();
2686 m_RotatorControlPanel->raise();
2690 else if (Options::astrometryUseRotator())
2696void Camera::setMaximumGuidingDeviation(
bool enable,
double value)
2698 m_LimitsUI->enforceGuideDeviation->setChecked(enable);
2700 m_LimitsUI->guideDeviation->setValue(value);
2703void Camera::setInSequenceFocus(
bool enable,
double HFR)
2705 m_LimitsUI->enforceAutofocusHFR->setChecked(enable);
2707 m_LimitsUI->hFRDeviation->setValue(HFR);
2716 KSNotification::sorry(message,
i18n(
"Could Not Open File"));
2720 state()->clearCapturedFramesMap();
2721 clearSequenceQueue();
2724 const bool result = process()->loadSequenceQueue(
fileURL, targetName, !m_standAlone);
2726 if (result ==
false)
2730 setObserverName(state()->observerName());
2733 if (state()->allJobs().size() > 0)
2734 syncGUIToJob(state()->allJobs().first());
2742bool Camera::saveSequenceQueue(
const QString &path)
2745 return process()->saveSequenceQueue(path);
2748void Camera::clearSequenceQueue()
2750 state()->setActiveJob(
nullptr);
2754 state()->allJobs().clear();
2756 while (state()->getSequence().count())
2757 state()->getSequence().pop_back();
2758 emit sequenceChanged(state()->getSequence());
2761QVariantMap Camera::getAllSettings()
const
2763 QVariantMap settings;
2770 if (name ==
"qt_spinbox_lineedit")
2772 settings.insert(name,
oneWidget->text());
2803void Camera::setAllSettings(
const QVariantMap &settings)
2807 disconnectSyncSettings();
2809 for (
auto &name : settings.keys())
2815 syncControl(settings, name, comboBox);
2823 syncControl(settings, name, doubleSpinBox);
2831 syncControl(settings, name,
spinBox);
2839 syncControl(settings, name,
checkbox);
2847 syncControl(settings, name,
groupbox);
2863 syncControl(settings, name, lineEdit);
2869 for (
auto &key : settings.keys())
2871 auto value = settings[key];
2873 Options::self()->setProperty(key.
toLatin1(), value);
2875 m_settings[key] = value;
2876 m_GlobalSettings[key] = value;
2879 emit settingsUpdated(getAllSettings());
2884 const int id = OpticalTrainManager::Instance()->id(
opticalTrainCombo->currentText());
2885 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
2886 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
2887 Options::setCaptureTrainID(
id);
2890 connectSyncSettings();
2893void Camera::setupOpticalTrainManager()
2895 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Camera::refreshOpticalTrain);
2902 ProfileSettings::Instance()->setOneSetting(ProfileSettings::CaptureOpticalTrain,
2904 refreshOpticalTrain();
2905 emit trainChanged();
2909void Camera::refreshOpticalTrain()
2914 trainB->setEnabled(
true);
2916 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
2917 if (m_standAlone || trainID.
isValid())
2919 auto id = m_standAlone ? Options::captureTrainID() : trainID.toUInt();
2920 Options::setCaptureTrainID(
id);
2923 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
2929 auto name = OpticalTrainManager::Instance()->name(
id);
2933 process()->refreshOpticalTrain(name);
2939 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
2940 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
2941 if (settings.isValid())
2943 auto map = settings.toJsonObject().toVariantMap();
2944 if (map != m_settings)
2947 setAllSettings(map);
2951 setSettings(m_GlobalSettings);
2957void Camera::syncLimitSettings()
2959 m_LimitsUI->enforceStartGuiderDrift->setChecked(Options::enforceStartGuiderDrift());
2960 m_LimitsUI->startGuideDeviation->setValue(Options::startGuideDeviation());
2961 m_LimitsUI->enforceGuideDeviation->setChecked(Options::enforceGuideDeviation());
2962 m_LimitsUI->guideDeviation->setValue(Options::guideDeviation());
2963 m_LimitsUI->guideDeviationReps->setValue(
static_cast<int>(Options::guideDeviationReps()));
2964 m_LimitsUI->enforceAutofocusHFR->setChecked(Options::enforceAutofocusHFR());
2965 m_LimitsUI->hFRThresholdPercentage->setValue(Options::hFRThresholdPercentage());
2966 m_LimitsUI->hFRDeviation->setValue(Options::hFRDeviation());
2967 m_LimitsUI->inSequenceCheckFrames->setValue(Options::inSequenceCheckFrames());
2968 m_LimitsUI->hFRCheckAlgorithm->setCurrentIndex(Options::hFRCheckAlgorithm());
2969 m_LimitsUI->enforceAutofocusOnTemperature->setChecked(Options::enforceAutofocusOnTemperature());
2970 m_LimitsUI->maxFocusTemperatureDelta->setValue(Options::maxFocusTemperatureDelta());
2971 m_LimitsUI->enforceRefocusEveryN->setChecked(Options::enforceRefocusEveryN());
2972 m_LimitsUI->refocusEveryN->setValue(
static_cast<int>(Options::refocusEveryN()));
2973 m_LimitsUI->refocusAfterMeridianFlip->setChecked(Options::refocusAfterMeridianFlip());
2976void Camera::settleSettings()
2978 state()->setDirty(
true);
2979 emit settingsUpdated(getAllSettings());
2981 const int id = OpticalTrainManager::Instance()->id(
opticalTrainCombo->currentText());
2982 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
2983 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
2984 Options::setCaptureTrainID(
id);
2987void Camera::syncSettings()
3002 key =
dsb->objectName();
3003 value =
dsb->value();
3009 value = sb->
value();
3018 key =
gb->objectName();
3019 value =
gb->isChecked();
3023 key =
rb->objectName();
3025 if (
rb->isChecked() ==
false)
3027 settings().remove(key);
3034 key =
cbox->objectName();
3035 value =
cbox->currentText();
3039 key =
le->objectName();
3046 settings()[key] = value;
3047 m_GlobalSettings[key] = value;
3049 Options::self()->setProperty(key.
toLatin1(), value);
3050 m_DebounceTimer.start();
3054void Camera::connectSyncSettings()
3092void Camera::disconnectSyncSettings()
3122 if (
oneWidget->objectName() ==
"qt_spinbox_lineedit")
3130 if (!m_settings.contains(key) || m_settings[key].toStringList() != list)
3132 m_settings[key] =
list;
3133 m_DebounceTimer.start();
3137void Camera::storeTrainKeyString(
const QString &key,
const QString &str)
3139 if (!m_settings.contains(key) || m_settings[key].toString() != str)
3141 m_settings[key] = str;
3142 m_DebounceTimer.start();
3146void Camera::setupFilterManager()
3149 if (filterManager())
3150 filterManager()->disconnect(
this);
3153 Manager::Instance()->createFilterManager(devices()->filterWheel());
3156 Manager::Instance()->getFilterManager(devices()->filterWheel()->getDeviceName(), filterManager());
3158 devices()->setFilterManager(filterManager());
3160 connect(filterManager().
get(), &FilterManager::updated,
this, [
this]()
3162 emit filterManagerUpdated(devices()->filterWheel());
3166 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::newFilterStatus);
3170 filterManager()->refreshFilterModel();
3171 filterManager()->show();
3172 filterManager()->raise();
3175 connect(filterManager().
get(), &FilterManager::failed,
this, [
this]()
3179 appendLogText(
i18n(
"Filter operation failed."));
3185 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::setFilterStatus);
3189 &LedStatusWidget::setFilterState);
3191 connect(filterManager().
get(), &FilterManager::labelsChanged,
this, [
this]()
3195 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3196 updateCurrentFilterPosition();
3199 connect(filterManager().
get(), &FilterManager::positionChanged,
this, [
this]()
3201 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3202 updateCurrentFilterPosition();
3206void Camera::refreshFilterSettings()
3210 if (!devices()->filterWheel())
3217 devices()->setFilterManager(filterManager());
3226 setupFilterManager();
3228 process()->updateFilterInfo();
3230 const auto labels = process()->filterLabels();
3234 storeTrainKey(KEY_FILTERS, labels);
3236 updateCurrentFilterPosition();
3238 filterEditB->setEnabled(state()->getCurrentFilterPosition() > 0);
3239 filterManagerB->setEnabled(state()->getCurrentFilterPosition() > 0);
3241 FilterPosCombo->setCurrentIndex(state()->getCurrentFilterPosition() - 1);
3244void Camera::updateCurrentFilterPosition()
3247 state()->setCurrentFilterPosition(m_FilterManager->getFilterPosition(),
3253void Camera::setFilterWheel(
QString name)
3259 if (devices()->filterWheel() && devices()->filterWheel()->getDeviceName() == name)
3261 refreshFilterSettings();
3265 auto isConnected = devices()->filterWheel() && devices()->filterWheel()->isConnected();
3270 refreshFilterSettings();
3272 if (devices()->filterWheel())
3273 emit settingsUpdated(getAllSettings());
3278 return m_DeviceAdaptor->getActiveCamera();
3283 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3284 if (activeCamera() && trainID.
isValid())
3286 auto id = trainID.
toUInt();
3287 auto name = OpticalTrainManager::Instance()->name(
id);
3288 return OpticalTrainManager::Instance()->getScope(name);
3294double Camera::currentReducer()
3296 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3297 if (activeCamera() && trainID.
isValid())
3299 auto id = trainID.
toUInt();
3300 auto name = OpticalTrainManager::Instance()->name(
id);
3301 return OpticalTrainManager::Instance()->getReducer(name);
3307double Camera::currentAperture()
3309 auto scope = currentScope();
3311 double focalLength = scope[
"focal_length"].toDouble(-1);
3312 double aperture = scope[
"aperture"].toDouble(-1);
3313 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3317 aperture = focalLength * focalRatio;
3322void Camera::openExposureCalculatorDialog()
3329 auto scope = currentScope();
3330 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3333 auto aperture = currentAperture();
3336 if (devices()->getActiveCamera() !=
nullptr)
3338 qCInfo(
KSTARS_EKOS_CAPTURE) <<
"set ExposureCalculator preferred camera to active camera id: "
3339 << devices()->getActiveCamera()->getDeviceName();
3345 devices()->getActiveCamera()->getDeviceName()));
3350void Camera::handleScriptsManager()
3359void Camera::showTemperatureRegulation()
3361 if (!devices()->getActiveCamera())
3370 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_SLOPE", &
rMin, &
rMax, &
rStep);
3371 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_THRESHOLD", &
tMin, &
tMax, &
tStep);
3373 QLabel rampLabel(
i18nc(
"Maximum temperature variation over time when regulating.",
"Ramp (°C/min):"));
3380 "<p>Maximum temperature change per minute when cooling or warming the camera. Set zero to disable."
3381 "<p>This setting is read from and stored in the INDI camera driver configuration."
3391 "<p>Maximum difference between camera and target temperatures triggering regulation."
3392 "<p>This setting is read from and stored in the INDI camera driver configuration."
3403 dialog->setWindowTitle(
i18nc(
"@title:window",
"Set Temperature Regulation"));
3405 dialog->setLayout(&layout);
3406 dialog->setMinimumWidth(300);
3410 if (devices()->getActiveCamera())
3415void Camera::createDSLRDialog()
3417 m_DSLRInfoDialog.reset(
new DSLRInfo(
this, devices()->getActiveCamera()));
3419 connect(m_DSLRInfoDialog.get(), &DSLRInfo::infoChanged,
this, [
this]()
3421 if (devices()->getActiveCamera())
3422 addDSLRInfo(QString(devices()->getActiveCamera()->getDeviceName()),
3423 m_DSLRInfoDialog->sensorMaxWidth,
3424 m_DSLRInfoDialog->sensorMaxHeight,
3425 m_DSLRInfoDialog->sensorPixelW,
3426 m_DSLRInfoDialog->sensorPixelH);
3429 m_DSLRInfoDialog->show();
3431 emit dslrInfoRequested(devices()->getActiveCamera()->getDeviceName());
3434void Camera::showObserverDialog()
3439 for (
auto &o : m_observerList)
3465 for (
auto &o : m_observerList)
3475 layout->addWidget(&label);
3485void Camera::onStandAloneShow(
QShowEvent *event)
3487 OpticalTrainSettings::Instance()->setOpticalTrainID(Options::captureTrainID());
3488 auto oneSetting = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
3489 setSettings(
oneSetting.toJsonObject().toVariantMap());
3497 m_standAloneUseCcdGain =
true;
3498 m_standAloneUseCcdOffset =
true;
3499 if (m_settings.contains(KEY_GAIN_KWD) && m_settings[KEY_GAIN_KWD].toString() ==
"CCD_CONTROLS")
3500 m_standAloneUseCcdGain =
false;
3501 if (m_settings.contains(KEY_OFFSET_KWD) && m_settings[KEY_OFFSET_KWD].toString() ==
"CCD_CONTROLS")
3502 m_standAloneUseCcdOffset =
false;
3524void Camera::setStandAloneGain(
double value)
3528 if (m_standAloneUseCcdGain)
3534 propertyMap[
"CCD_GAIN"] =
ccdGain;
3538 propertyMap[
"CCD_GAIN"].remove(
"GAIN");
3539 if (propertyMap[
"CCD_GAIN"].size() == 0)
3540 propertyMap.remove(
"CCD_GAIN");
3549 propertyMap[
"CCD_CONTROLS"] =
ccdGain;
3553 propertyMap[
"CCD_CONTROLS"].remove(
"Gain");
3554 if (propertyMap[
"CCD_CONTROLS"].size() == 0)
3555 propertyMap.remove(
"CCD_CONTROLS");
3559 m_customPropertiesDialog->setCustomProperties(propertyMap);
3562void Camera::setStandAloneOffset(
double value)
3566 if (m_standAloneUseCcdOffset)
3576 propertyMap[
"CCD_OFFSET"].remove(
"OFFSET");
3577 if (propertyMap[
"CCD_OFFSET"].size() == 0)
3578 propertyMap.remove(
"CCD_OFFSET");
3587 propertyMap[
"CCD_CONTROLS"] =
ccdOffset;
3591 propertyMap[
"CCD_CONTROLS"].remove(
"Offset");
3592 if (propertyMap[
"CCD_CONTROLS"].size() == 0)
3593 propertyMap.remove(
"CCD_CONTROLS");
3597 m_customPropertiesDialog->setCustomProperties(propertyMap);
3600void Camera::setVideoStreamEnabled(
bool enabled)
3615void Camera::setCoolerToggled(
bool enabled)
3617 auto isToggled = (!enabled &&
coolerOnB->isChecked()) || (enabled &&
coolerOffB->isChecked());
3628 appendLogText(enabled ?
i18n(
"Cooler is on") :
i18n(
"Cooler is off"));
3631void Camera::setFilterStatus(FilterState
filterState)
3633 if (
filterState != state()->getFilterManagerState())
3634 qCDebug(
KSTARS_EKOS_CAPTURE) <<
"Filter state changed from" << Ekos::getFilterStatusString(
3635 state()->getFilterManagerState()) <<
"to" << Ekos::getFilterStatusString(
filterState);
3636 if (state()->getCaptureState() == CAPTURE_CHANGING_FILTER)
3641 appendLogText(
i18n(
"Changing focus offset by %1 steps...",
3642 filterManager()->getTargetFilterOffset()));
3646 appendLogText(
i18n(
"Changing filter to %1...",
3647 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3650 case FILTER_AUTOFOCUS:
3651 appendLogText(
i18n(
"Auto focus on filter change..."));
3652 clearAutoFocusHFR();
3656 if (state()->getFilterManagerState() == FILTER_CHANGE)
3658 appendLogText(
i18n(
"Filter set to %1.",
3659 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3670void Camera::resetJobs()
3676 if (m_JobUnderEdit ==
true)
3682 updateJobTable(job);
3688 nullptr,
i18n(
"Are you sure you want to reset status of all jobs?"),
i18n(
"Reset job status"),
3697 updateJobTable(job);
3702 state()->clearCapturedFramesMap();
3705 state()->setIgnoreJobProgress(Options::alwaysResetSequenceWhenStarting());
3708 startB->setEnabled(
true);
3713 if (i.
row() < 0 || (i.
row() + 1) > state()->allJobs().size())
3718 if (job ==
nullptr || job->jobType() == SequenceJob::JOBTYPE_DARKFLAT)
3723 if (state()->isBusy())
3726 if (state()->allJobs().size() >= 2)
3729 queueDownB->setEnabled(i.
row() + 1 < state()->allJobs().size());
3738 if (selectJob(i) ==
false)
3741 appendLogText(
i18n(
"Editing job #%1...", i.
row() + 1));
3751 m_JobUnderEdit =
true;
3755void Camera::resetJobEdit(
bool cancelled)
3757 if (cancelled ==
true)
3758 appendLogText(
i18n(
"Editing job canceled."));
3760 m_JobUnderEdit =
false;
CameraChip class controls a particular chip in camera.
Camera class controls an INDI Camera device.
Rotator class handles control of INDI Rotator devices.
static KStars * Instance()
Dialog to add new observers.
Sequence Job is a container for the details required to capture a series of images.
The sky coordinates of a point in the sky.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
bool insert(Part *part, qint64 *insertId=nullptr)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
@ CAPTURE_SETTING_ROTATOR
@ CAPTURE_SETTING_TEMPERATURE
ISD is a collection of INDI Standard Devices.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
bool isValid(QStringView ifopt)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
KIOCORE_EXPORT void add(const QString &fileClass, const QString &directory)
QAction * up(const QObject *recvr, const char *slot, QObject *parent)
QString name(StandardAction id)
const QList< QKeySequence > & begin()
QString label(StandardShortcut id)
const QList< QKeySequence > & end()
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void doubleClicked(const QModelIndex &index)
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
void currentIndexChanged(int index)
void currentTextChanged(const QString &text)
QString toNativeSeparators(const QString &pathName)
void valueChanged(double d)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, Options options)
QUrl getOpenFileUrl(QWidget *parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, Options options, const QStringList &supportedSchemes)
QUrl getSaveFileUrl(QWidget *parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, Options options, const QStringList &supportedSchemes)
QIcon fromTheme(const QString &name)
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
void textChanged(const QString &text)
void textEdited(const QString &text)
qsizetype count() const const
bool isEmpty() const const
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QByteArray toLatin1() const const
QTextStream & bin(QTextStream &stream)
void setText(const QString &text)
void setTextAlignment(Qt::Alignment alignment)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)
bool isValid() const const
bool toBool() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
QString toString() const const
uint toUInt(bool *ok) const const