8#include "capturemodulestate.h"
12#include "kstarsdata.h"
13#include "auxiliary/ksmessagebox.h"
14#include "ekos/manager.h"
15#include "ekos/auxiliary/darklibrary.h"
16#include "ekos/auxiliary/filtermanager.h"
17#include "ekos/auxiliary/opticaltrainmanager.h"
18#include "ekos/auxiliary/opticaltrainsettings.h"
19#include "ekos/auxiliary/profilesettings.h"
20#include "ekos/auxiliary/rotatorutils.h"
21#include "capturedeviceadaptor.h"
22#include "cameraprocess.h"
23#include "sequencequeue.h"
24#include "scriptsmanager.h"
25#include "dslrinfodialog.h"
26#include "ui_dslrinfo.h"
27#include "exposurecalculator/exposurecalculatordialog.h"
29#include "indi/driverinfo.h"
30#include "indi/indirotator.h"
31#include "oal/observeradd.h"
33#include <ekos_capture_debug.h>
40#define KEY_FORMATS "formatsList"
41#define KEY_GAIN_KWD "ccdGainKeyword"
42#define KEY_OFFSET_KWD "ccdOffsetKeyword"
43#define KEY_TEMPERATURE "ccdTemperatures"
44#define KEY_TIMESTAMP "timestamp"
45#define KEY_FILTERS "filtersList"
46#define KEY_ISOS "isoList"
47#define KEY_INDEX "isoIndex"
48#define KEY_GAIN_KWD "ccdGainKeyword"
49#define KEY_OFFSET_KWD "ccdOffsetKeyword"
51#define QCDEBUG qCDebug(KSTARS_EKOS_CAPTURE) << QString("[%1]").arg(getCameraName())
52#define QCINFO qCInfo(KSTARS_EKOS_CAPTURE) << QString("[%1]").arg(getCameraName())
53#define QCWARNING qCWarning(KSTARS_EKOS_CAPTURE) << QString("[%1]").arg(getCameraName())
57const QStringList standAloneKeys = {KEY_FORMATS, KEY_GAIN_KWD, KEY_OFFSET_KWD,
58 KEY_TEMPERATURE, KEY_TIMESTAMP, KEY_FILTERS,
59 KEY_ISOS, KEY_INDEX, KEY_GAIN_KWD, KEY_OFFSET_KWD
61QVariantMap copyStandAloneSettings(
const QVariantMap &settings)
63 QVariantMap foundSettings;
64 for (
const auto &k : standAloneKeys)
66 auto v = settings.find(k);
67 if (v != settings.end())
68 foundSettings[k] = *v;
77Camera::Camera(
int id,
bool standAlone,
QWidget *parent)
78 :
QWidget{parent}, m_standAlone(standAlone), m_cameraId(id)
83Camera::Camera(
bool standAlone,
QWidget *parent) :
QWidget{parent}, m_standAlone(standAlone), m_cameraId(0)
88void Ekos::Camera::init()
91 m_cameraState.
reset(
new CameraState());
92 m_DeviceAdaptor.
reset(
new CaptureDeviceAdaptor());
93 m_cameraProcess.reset(
new CameraProcess(state(), m_DeviceAdaptor));
95 m_customPropertiesDialog.reset(
new CustomProperties());
96 m_LimitsDialog =
new QDialog(
this);
97 m_LimitsUI.reset(
new Ui::Limits());
98 m_LimitsUI->setupUi(m_LimitsDialog);
100 m_CalibrationDialog =
new QDialog(
this);
101 m_CalibrationUI.reset(
new Ui::Calibration());
102 m_CalibrationUI->setupUi(m_CalibrationDialog);
104 m_scriptsManager =
new ScriptsManager(
this);
109 auto title =
i18n(
"Capture Sequence Editor: %1", m_LimitsDialog->windowTitle());
110 m_LimitsDialog->setWindowTitle(title);
111 title =
i18n(
"Capture Sequence Editor: %1", m_scriptsManager->windowTitle());
112 m_scriptsManager->setWindowTitle(title);
120 targetDriftLabel->setVisible(
false);
121 targetDrift->setVisible(
false);
122 targetDriftUnit->setVisible(
false);
123 avgDownloadTime->setVisible(
false);
124 avgDownloadLabel->setVisible(
false);
125 secLabel->setVisible(
false);
126 darkB->setChecked(Options::autoDark());
166 addToQueueB->setToolTip(
i18n(
"Add job to sequence queue"));
167 removeFromQueueB->setToolTip(
i18n(
"Remove job from sequence queue"));
169 if (Options::remoteCaptureDirectory().isEmpty() ==
false)
171 fileRemoteDirT->setText(Options::remoteCaptureDirectory());
174 if(!Options::captureDirectory().isEmpty())
175 fileDirectoryT->setText(Options::captureDirectory());
184 for (
auto &button : qButtons)
185 button->setAutoDefault(
false);
189 refreshOpticalTrain();
194 foreach (
auto job, state()->allJobs())
197 state()->allJobs().clear();
200void Camera::initCamera()
202 KStarsData::Instance()->
userdb()->GetAllDSLRInfos(state()->DSLRInfos());
203 state()->getSequenceQueue()->loadOptions();
205 if (state()->DSLRInfos().count() > 0)
207 QCDEBUG <<
"DSLR Cameras Info:";
208 QCDEBUG << state()->DSLRInfos();
211 setupOpticalTrainManager();
214 state()->getMeridianFlipState();
231 restartCamera(activeCamera()->getDeviceName());
236 static_cast<void(Camera::*)()
>(&Camera::saveSequenceQueue));
239 &Camera::selectedJobChanged);
243 resetJobEdit(m_JobUnderEdit);
268 connect(m_FilterManager.
get(), &FilterManager::ready,
this, &Camera::updateCurrentFilterPosition);
273 state()->updateHFRThreshold();
274 generatePreviewFilename();
285 m_CalibrationUI->captureCalibrationParkMount->setChecked(false);
290 m_CalibrationUI->captureCalibrationWall->setChecked(false);
300 if (devices()->getActiveCamera())
302 QVariantMap auxInfo = devices()->getActiveCamera()->getDriverInfo()->getAuxInfo();
303 auxInfo[
QString(
"%1_TC").
arg(devices()->getActiveCamera()->getDeviceName())] = toggled;
304 devices()->getActiveCamera()->getDriverInfo()->setAuxInfo(auxInfo);
309 if (devices()->getActiveCamera())
310 devices()->getActiveCamera()->setTemperature(cameraTemperatureN->value());
314 if (devices()->getActiveCamera())
315 devices()->getActiveCamera()->setCoolerControl(
true);
319 if (devices()->getActiveCamera())
320 devices()->getActiveCamera()->setCoolerControl(
false);
326 placeholderFormatT->setText(KSUtils::getDefaultPath(
"PlaceholderFormat"));
330 &Camera::checkFrameType);
335 if (checked == false)
336 state()->getRefocusState()->setInSequenceFocus(false);
342 connect(m_cameraState.
get(), &CameraState::newLimitFocusHFR,
this, [
this](
double hfr)
344 m_LimitsUI->hFRDeviation->setValue(hfr);
347 state()->getCaptureDelayTimer().setSingleShot(
true);
351 state()->getCaptureTimeout().setSingleShot(
true);
359 fileRemoteDirT->setEnabled(index != 0);
364 customPropertiesDialog()->
show();
365 customPropertiesDialog()->
raise();
368 connect(customPropertiesDialog(), &CustomProperties::valueChanged,
this, [&]()
370 const double newGain = getGain();
371 if (captureGainN && newGain >= 0)
372 captureGainN->setValue(newGain);
373 const int newOffset = getOffset();
375 captureOffsetN->setValue(newOffset);
379 connect(m_cameraState.
data(), &CameraState::newStatus, captureStatusWidget, &LedStatusWidget::setCaptureState);
384 loadGlobalSettings();
385 connectSyncSettings();
389 updateHFRCheckAlgo();
392 updateHFRCheckAlgo();
395 updateHFRCheckAlgo();
402 generatePreviewFilename();
407 generatePreviewFilename();
411 &Camera::generatePreviewFilename);
414 generatePreviewFilename();
415 QCDEBUG <<
"Changed target to" << targetNameT->text() <<
"because of user edit";
418 placeholderFormatT->setText(Options::placeholderFormat());
421 generatePreviewFilename();
425 connect(m_cameraState.
data(), &CameraState::captureBusy,
this, &Camera::setBusy);
426 connect(m_cameraState.
data(), &CameraState::startCapture,
this, &Camera::start);
427 connect(m_cameraState.
data(), &CameraState::abortCapture,
this, &Camera::abort);
428 connect(m_cameraState.
data(), &CameraState::suspendCapture,
this, &Camera::suspend);
429 connect(m_cameraState.
data(), &CameraState::newLog,
this, &Camera::appendLogText);
430 connect(m_cameraState.
data(), &CameraState::sequenceChanged,
this, &Camera::sequenceChanged);
431 connect(m_cameraState.
data(), &CameraState::updatePrepareState,
this, &Camera::updatePrepareState);
432 connect(m_cameraState.
data(), &CameraState::newFocusStatus,
this, &Camera::updateFocusStatus);
433 connect(m_cameraState.
data(), &CameraState::runAutoFocus,
this,
434 [&](AutofocusReason autofocusReason,
const QString & reasonInfo)
436 emit runAutoFocus(autofocusReason, reasonInfo, opticalTrain());
438 connect(m_cameraState.
data(), &CameraState::resetFocusFrame,
this, [&]()
440 emit resetFocusFrame(opticalTrain());
442 connect(m_cameraState.
data(), &CameraState::adaptiveFocus,
this, [&]()
444 emit adaptiveFocus(opticalTrain());
446 connect(m_cameraProcess.data(), &CameraProcess::abortFocus,
this, [&]()
448 emit abortFocus(opticalTrain());
450 connect(m_cameraState.
data(), &CameraState::newMeridianFlipStage,
this, &Camera::updateMeridianFlipStage);
451 connect(m_cameraState.
data(), &CameraState::guideAfterMeridianFlip,
this, &Camera::guideAfterMeridianFlip);
452 connect(m_cameraState.
data(), &CameraState::resetNonGuidedDither,
this, [&]()
456 emit resetNonGuidedDither();
458 connect(m_cameraState.
data(), &CameraState::newStatus,
this, &Camera::updateCameraStatus);
459 connect(m_cameraState.
data(), &CameraState::meridianFlipStarted,
this, [&]()
461 emit meridianFlipStarted(opticalTrain());
464 connect(m_cameraProcess.data(), &CameraProcess::refreshCamera,
this, &Camera::updateCamera);
465 connect(m_cameraProcess.data(), &CameraProcess::sequenceChanged,
this, &Camera::sequenceChanged);
466 connect(m_cameraProcess.data(), &CameraProcess::addJob,
this, &Camera::addJob);
467 connect(m_cameraProcess.data(), &CameraProcess::newExposureProgress,
this, [&](
SequenceJob * job)
469 emit newExposureProgress(job, opticalTrain());
471 connect(m_cameraProcess.data(), &CameraProcess::newDownloadProgress,
this, [&](
double downloadTimeLeft)
473 emit updateDownloadProgress(downloadTimeLeft, opticalTrain());
477 emit newImage(job, data, opticalTrain());
479 connect(m_cameraProcess.data(), &CameraProcess::captureComplete,
this, [&](
const QVariantMap & metadata)
481 emit captureComplete(metadata, opticalTrain());
483 connect(m_cameraProcess.data(), &CameraProcess::updateCaptureCountDown,
this, &Camera::updateCaptureCountDown);
484 connect(m_cameraProcess.data(), &CameraProcess::processingFITSfinished,
this, &Camera::processingFITSfinished);
485 connect(m_cameraProcess.data(), &CameraProcess::captureStopped,
this, &Camera::captureStopped);
486 connect(m_cameraProcess.data(), &CameraProcess::darkFrameCompleted,
this, &Camera::imageCapturingCompleted);
487 connect(m_cameraProcess.data(), &CameraProcess::updateMeridianFlipStage,
this, &Camera::updateMeridianFlipStage);
488 connect(m_cameraProcess.data(), &CameraProcess::syncGUIToJob,
this, &Camera::syncGUIToJob);
489 connect(m_cameraProcess.data(), &CameraProcess::refreshCameraSettings,
this, &Camera::refreshCameraSettings);
490 connect(m_cameraProcess.data(), &CameraProcess::updateFrameProperties,
this, &Camera::updateFrameProperties);
491 connect(m_cameraProcess.data(), &CameraProcess::rotatorReverseToggled,
this, &Camera::setRotatorReversed);
492 connect(m_cameraProcess.data(), &CameraProcess::refreshFilterSettings,
this, &Camera::refreshFilterSettings);
493 connect(m_cameraProcess.data(), &CameraProcess::suspendGuiding,
this, &Camera::suspendGuiding);
494 connect(m_cameraProcess.data(), &CameraProcess::resumeGuiding,
this, &Camera::resumeGuiding);
495 connect(m_cameraProcess.data(), &CameraProcess::driverTimedout,
this, &Camera::driverTimedout);
496 connect(m_cameraProcess.data(), &CameraProcess::createJob, [
this](SequenceJob::SequenceJobType jobType)
499 process()->jobCreated(createJob(jobType));
501 connect(m_cameraProcess.data(), &CameraProcess::updateJobTable,
this, &Camera::updateJobTable);
502 connect(m_cameraProcess.data(), &CameraProcess::newLog,
this, &Camera::appendLogText);
503 connect(m_cameraProcess.data(), &CameraProcess::stopCapture,
this, &Camera::stop);
504 connect(m_cameraProcess.data(), &CameraProcess::jobStarting,
this, &Camera::jobStarting);
505 connect(m_cameraProcess.data(), &CameraProcess::cameraReady,
this, &Camera::ready);
506 connect(m_cameraProcess.data(), &CameraProcess::captureAborted,
this, &Camera::captureAborted);
507 connect(m_cameraProcess.data(), &CameraProcess::captureRunning,
this, &Camera::captureRunning);
508 connect(m_cameraProcess.data(), &CameraProcess::captureImageStarted,
this, &Camera::captureImageStarted);
509 connect(m_cameraProcess.data(), &CameraProcess::jobExecutionPreparationStarted,
this,
510 &Camera::jobExecutionPreparationStarted);
511 connect(m_cameraProcess.data(), &CameraProcess::jobPrepared,
this, &Camera::jobPrepared);
512 connect(m_cameraProcess.data(), &CameraProcess::captureTarget,
this, &Camera::setTargetName);
513 connect(m_cameraProcess.data(), &CameraProcess::downloadingFrame,
this, [
this]()
515 captureStatusWidget->setStatus(i18n(
"Downloading..."), Qt::yellow);
517 connect(m_cameraProcess.data(), &CameraProcess::requestAction,
this, [&](CaptureWorkflowActionType action)
519 emit requestAction(m_cameraId, action);
523 connect(m_cameraState.
data(), &CameraState::executeActiveJob, m_cameraProcess.data(),
525 connect(m_cameraState.
data(), &CameraState::captureStarted, m_cameraProcess.data(),
527 connect(m_cameraState.
data(), &CameraState::requestAction,
this, [&](CaptureWorkflowActionType action)
529 emit requestAction(m_cameraId, action);
531 connect(m_cameraState.
data(), &CameraState::checkFocus,
this, [&](
double hfr)
533 emit checkFocus(hfr, opticalTrain());
535 connect(m_cameraState.
data(), &CameraState::resetNonGuidedDither,
this, [&]()
538 emit resetNonGuidedDither();
542 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::newCCDTemperatureValue,
this,
544 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::CameraConnected,
this, [
this](
bool connected)
546 CaptureSettingsGroup->setEnabled(connected);
547 fileSettingsGroup->setEnabled(connected);
548 sequenceBox->setEnabled(connected);
549 for (auto &oneChild : sequenceControlsButtonGroup->buttons())
550 oneChild->setEnabled(connected);
553 trainLayout->setEnabled(true);
555 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::FilterWheelConnected,
this, [
this](
bool connected)
557 FilterPosLabel->setEnabled(connected);
558 FilterPosCombo->setEnabled(connected);
559 filterManagerB->setEnabled(connected);
561 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::newRotator,
this, &Camera::setRotator);
562 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::newRotatorAngle,
this, &Camera::updateRotatorAngle,
564 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::newFilterWheel,
this, &Camera::setFilterWheel);
567 connect(m_cameraState.
data(), &CameraState::newFilterPosition,
568 m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::setFilterPosition);
569 connect(m_cameraState.
data(), &CameraState::abortFastExposure,
570 m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::abortFastExposure);
573 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::scopeStatusChanged,
574 m_cameraState.
data(), &CameraState::setScopeState);
575 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::pierSideChanged,
576 m_cameraState.
data(), &CameraState::setPierSide);
577 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::scopeParkStatusChanged,
578 m_cameraState.
data(), &CameraState::setScopeParkState);
579 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::domeStatusChanged,
580 m_cameraState.
data(), &CameraState::setDomeState);
581 connect(m_DeviceAdaptor.
data(), &CaptureDeviceAdaptor::dustCapStatusChanged,
582 m_cameraState.
data(), &CameraState::dustCapStateChanged);
585void Camera::updateRotatorAngle(
double value)
587 IPState RState = devices()->rotator()->absoluteAngleState();
588 if (RState == IPS_OK)
589 m_RotatorControlPanel->updateRotator(value);
591 m_RotatorControlPanel->updateGauge(value);
594void Camera::setRotatorReversed(
bool toggled)
596 m_RotatorControlPanel->reverseDirection->setEnabled(
true);
597 m_RotatorControlPanel->reverseDirection->blockSignals(
true);
598 m_RotatorControlPanel->reverseDirection->setChecked(toggled);
599 m_RotatorControlPanel->reverseDirection->blockSignals(
false);
602void Camera::updateCCDTemperature(
double value)
604 if (cameraTemperatureS->isEnabled() ==
false && devices()->getActiveCamera())
606 if (devices()->getActiveCamera()->getPermission(
"CCD_TEMPERATURE") != IP_RO)
607 process()->checkCamera();
610 temperatureOUT->setText(
QString(
"%L1º").arg(value, 0,
'f', 1));
612 if (cameraTemperatureN->cleanText().isEmpty())
613 cameraTemperatureN->setValue(value);
616void Camera::setFocusStatus(FocusState newstate)
619 state()->updateFocusState(newstate);
622void Camera::updateFocusStatus(FocusState newstate)
624 if ((state()->getRefocusState()->isRefocusing()
625 || state()->getRefocusState()->isInSequenceFocus()) && activeJob()
626 && activeJob()->getStatus() == JOB_BUSY)
631 appendLogText(
i18n(
"Focus complete."));
632 captureStatusWidget->setStatus(
i18n(
"Focus complete."),
Qt::yellow);
636 captureStatusWidget->setStatus(
i18n(
"Autofocus failed."),
Qt::darkRed);
645void Camera::updateCamera(
bool isValid)
647 auto isConnected = activeCamera() && activeCamera()->isConnected();
648 CaptureSettingsGroup->setEnabled(isConnected);
649 fileSettingsGroup->setEnabled(isConnected);
650 sequenceBox->setEnabled(isConnected);
651 for (
auto &oneChild : sequenceControlsButtonGroup->buttons())
652 oneChild->setEnabled(isConnected);
656 auto name = activeCamera()->getDeviceName();
657 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(name, currentScope()[
"name"].
toString()));
658 emit settingsUpdated(getAllSettings());
659 emit refreshCamera(m_cameraId,
true);
662 emit refreshCamera(m_cameraId,
false);
666void Camera::refreshCameraSettings()
670 auto camera = activeCamera();
671 auto targetChip = devices()->getActiveChip();
673 if (!m_standAlone && (!camera || !targetChip || !targetChip->getCCD() || targetChip->isCapturing()))
679 if (camera->hasCoolerControl())
681 coolerOnB->setEnabled(
true);
682 coolerOffB->setEnabled(
true);
683 coolerOnB->setChecked(camera->isCoolerOn());
684 coolerOffB->setChecked(!camera->isCoolerOn());
688 coolerOnB->setEnabled(
false);
689 coolerOnB->setChecked(
false);
690 coolerOffB->setEnabled(
false);
691 coolerOffB->setChecked(
false);
694 updateFrameProperties();
696 updateCaptureFormats();
698 customPropertiesDialog()->setCCD(camera);
700 liveVideoB->setEnabled(camera->hasVideoStream());
701 if (camera->hasVideoStream())
702 setVideoStreamEnabled(camera->isStreamingEnabled());
718 DarkLibrary::Instance()->checkCamera();
721void Camera::processCameraNumber(INDI::Property prop)
723 if (devices()->getActiveCamera() ==
nullptr)
726 if ((prop.isNameMatch(
"CCD_FRAME") && state()->useGuideHead() ==
false) ||
727 (prop.isNameMatch(
"GUIDER_FRAME") && state()->useGuideHead()))
728 updateFrameProperties();
729 else if ((prop.isNameMatch(
"CCD_INFO") && state()->useGuideHead() ==
false) ||
730 (prop.isNameMatch(
"GUIDER_INFO") && state()->useGuideHead()))
731 updateFrameProperties(1);
732 else if (prop.isNameMatch(
"CCD_TRANSFER_FORMAT") || prop.isNameMatch(
"CCD_CAPTURE_FORMAT"))
733 updateCaptureFormats();
734 else if (prop.isNameMatch(
"CCD_CONTROLS"))
736 auto nvp = prop.getNumber();
737 auto gain = nvp->findWidgetByName(
"Gain");
740 auto offset = nvp->findWidgetByName(
"Offset");
744 else if (prop.isNameMatch(
"CCD_GAIN"))
746 auto nvp = prop.getNumber();
747 currentGainLabel->setText(
QString::number(nvp->at(0)->getValue(),
'f', 0));
749 else if (prop.isNameMatch(
"CCD_OFFSET"))
751 auto nvp = prop.getNumber();
752 currentOffsetLabel->setText(
QString::number(nvp->at(0)->getValue(),
'f', 0));
757void Camera::updateTargetDistance(
double targetDiff)
760 targetDriftLabel->setVisible(
true);
761 targetDrift->setVisible(
true);
762 targetDriftUnit->setVisible(
true);
764 targetDrift->setText(
QString(
"%L1").arg(targetDiff, 0,
'd', 1));
775 return CCDFrameTypeNames[
type];
781 return CCDFrameTypeNames[
type];
783 return QString(
"%1 %2").
arg(filter).
arg(CCDFrameTypeNames[type]);
789 return CCDFrameTypeNames[
type];
794void Camera::captureRunning()
796 emit captureStarting(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(),
797 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString());
798 if (isActiveJobPreview())
799 frameInfoLabel->setText(
"Expose (-/-):");
801 frameInfoLabel->setText(
QString(
"%1 (%L3/%L4):").arg(frameLabel(activeJob()->getFrameType(),
802 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()))
803 .arg(activeJob()->getCompleted()).arg(activeJob()->getCoreProperty(
804 SequenceJob::SJ_Count).toInt()));
807 avgDownloadTime->setVisible(
true);
808 avgDownloadLabel->setVisible(
true);
809 secLabel->setVisible(
true);
811 avgDownloadTime->setText(
QString(
"%L1").arg(state()->averageDownloadTime(), 0,
'd', 2));
814 if (state()->isLooping() ==
false && activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
815 appendLogText(
i18n(
"Capturing %1-second %2 image...",
816 QString(
"%L1").arg(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f', 3),
817 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()));
820void Camera::captureImageStarted()
822 if (devices()->filterWheel() !=
nullptr)
826 process()->updateFilterInfo();
827 updateCurrentFilterPosition();
831 if (activeJob()->getCalibrationStage() == SequenceJobState::CAL_CALIBRATION)
832 captureStatusWidget->setStatus(
i18n(
"Calibrating..."),
Qt::yellow);
835void Camera::jobExecutionPreparationStarted()
837 if (activeJob() ==
nullptr)
840 qWarning(KSTARS_EKOS_CAPTURE) <<
"jobExecutionPreparationStarted with null state()->getActiveJob().";
843 if (activeJob()->jobType() == SequenceJob::JOBTYPE_PREVIEW)
844 updateStartButtons(
true,
false);
849 int index = state()->allJobs().indexOf(job);
851 queueTable->selectRow(index);
853 if (activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
856 imgProgress->setEnabled(
true);
857 imgProgress->setMaximum(activeJob()->getCoreProperty(SequenceJob::SJ_Count).toInt());
858 imgProgress->setValue(activeJob()->getCompleted());
862void Camera::setTargetName(
const QString &newTargetName)
865 if (activeJob() ==
nullptr)
868 targetNameT->setText(newTargetName);
869 auto rows = queueTable->selectionModel()->selectedRows();
873 int pos = rows.constFirst().row();
875 if (state()->allJobs().
size() >
pos)
876 state()->allJobs().at(
pos)->setCoreProperty(SequenceJob::SJ_TargetName, newTargetName);
879 emit captureTarget(newTargetName);
883void Camera::jobStarting()
885 if (m_LimitsUI->enforceAutofocusHFR->isChecked() && state()->getRefocusState()->isAutoFocusReady() ==
false)
886 appendLogText(
i18n(
"Warning: in-sequence focusing is selected but autofocus process was not started."));
887 if (m_LimitsUI->enforceAutofocusOnTemperature->isChecked()
888 && state()->getRefocusState()->isAutoFocusReady() ==
false)
889 appendLogText(
i18n(
"Warning: temperature delta check is selected but autofocus process was not started."));
891 updateStartButtons(
true,
false);
895void Camera::capturePreview()
897 process()->capturePreview();
900void Camera::startFraming()
902 process()->capturePreview(
true);
905void Camera::generateDarkFlats()
907 const auto existingJobs = state()->allJobs().size();
908 uint8_t jobsAdded = 0;
910 for (
int i = 0; i < existingJobs; i++)
912 if (state()->allJobs().at(i)->getFrameType() != FRAME_FLAT)
915 syncGUIToJob(state()->allJobs().at(i));
917 captureTypeS->setCurrentIndex(FRAME_DARK);
918 createJob(SequenceJob::JOBTYPE_DARKFLAT);
924 appendLogText(
i18np(
"One dark flats job was created.",
"%1 dark flats jobs were created.", jobsAdded));
928void Camera::updateDownloadProgress(
double downloadTimeLeft,
const QString &devicename)
930 frameRemainingTime->setText(state()->imageCountDown().
toString(
"hh:mm:ss"));
931 emit newDownloadProgress(downloadTimeLeft, devicename);
934void Camera::updateCaptureCountDown(
int deltaMillis)
936 state()->imageCountDownAddMSecs(deltaMillis);
937 state()->sequenceCountDownAddMSecs(deltaMillis);
938 frameRemainingTime->setText(state()->imageCountDown().
toString(
"hh:mm:ss"));
939 if (!isActiveJobPreview())
940 jobRemainingTime->setText(state()->sequenceCountDown().
toString(
"hh:mm:ss"));
942 jobRemainingTime->setText(
"--:--:--");
948 createNewJobTableRow(job);
951void Camera::editJobFinished()
953 if (queueTable->currentRow() < 0)
954 QCWARNING <<
"Editing finished, but no row selected!";
956 int currentRow = queueTable->currentRow();
957 SequenceJob *job = state()->allJobs().at(currentRow);
958 updateJobFromUI(job);
961 updateJobTable(job,
true);
964 QJsonObject jsonJob = createJsonJob(job, currentRow);
965 state()->getSequence().replace(currentRow, jsonJob);
966 emit sequenceChanged(state()->getSequence());
969 appendLogText(
i18n(
"Job #%1 changes applied.", currentRow + 1));
972void Camera::imageCapturingCompleted()
980 if (state()->isLooping())
988 if (devices()->getActiveCamera()->isFastExposureEnabled() ==
false)
989 DarkLibrary::Instance()->disconnect(
this);
992 if (thejob->getCoreProperty(SequenceJob::SJ_Exposure).toDouble() >= 1)
993 KSNotification::event(
QLatin1String(
"EkosCaptureImageReceived"),
i18n(
"Captured image received"),
994 KSNotification::Capture);
997 if (thejob->jobType() == SequenceJob::JOBTYPE_PREVIEW)
1001 imgProgress->setValue(thejob->getCompleted());
1004void Camera::captureStopped()
1006 imgProgress->reset();
1007 imgProgress->setEnabled(
false);
1009 frameRemainingTime->setText(
"--:--:--");
1010 jobRemainingTime->setText(
"--:--:--");
1011 frameInfoLabel->setText(
i18n(
"Expose (-/-):"));
1014 auto captureState = state()->getCaptureState();
1016 updateStartButtons(
false,
false);
1019void Camera::processingFITSfinished(
bool success)
1022 if (success ==
false)
1026 if (devices()->getActiveCamera()
1027 && devices()->getActiveCamera()->getUploadMode() != ISD::Camera::UPLOAD_LOCAL)
1028 previewB->setEnabled(
true);
1030 imageCapturingCompleted();
1033void Camera::checkFrameType(
int index)
1035 calibrationB->setEnabled(index != FRAME_LIGHT);
1036 generateDarkFlatsB->setEnabled(index != FRAME_LIGHT);
1039void Camera::updateStartButtons(
bool start,
bool pause)
1045 startB->setToolTip(
i18n(
"Stop Sequence"));
1051 startB->setToolTip(
i18n(pause ?
"Resume Sequence" :
"Start Sequence"));
1053 pauseB->setEnabled(start && !pause);
1056void Camera::setBusy(
bool enable)
1058 previewB->setEnabled(!enable);
1059 loopB->setEnabled(!enable);
1060 opticalTrainCombo->setEnabled(!enable);
1061 trainB->setEnabled(!enable);
1068void Camera::updatePrepareState(CaptureState prepareState)
1070 state()->setCaptureState(prepareState);
1072 if (activeJob() ==
nullptr)
1074 qWarning(KSTARS_EKOS_CAPTURE) <<
"updatePrepareState with null activeJob().";
1079 switch (prepareState)
1082 appendLogText(
i18n(
"Setting temperature to %1 °C...", activeJob()->getTargetTemperature()));
1083 captureStatusWidget->setStatus(
i18n(
"Set Temp to %1 °C...", activeJob()->getTargetTemperature()),
1087 appendLogText(
i18n(
"Waiting for guide drift below %1\"...", Options::startGuideDeviation()));
1088 captureStatusWidget->setStatus(
i18n(
"Wait for Guider < %1\"...", Options::startGuideDeviation()),
Qt::yellow);
1092 appendLogText(
i18n(
"Setting camera to %1 degrees E of N...", activeJob()->getTargetRotation()));
1093 captureStatusWidget->setStatus(
i18n(
"Set Camera to %1 deg...", activeJob()->getTargetRotation()),
1103SequenceJob *Camera::createJob(SequenceJob::SequenceJobType jobtype, FilenamePreviewType filenamePreview)
1107 updateJobFromUI(job, filenamePreview);
1110 if (jobtype == SequenceJob::JOBTYPE_PREVIEW || filenamePreview != FILENAME_NOT_PREVIEW)
1114 if (checkUploadPaths(filenamePreview) ==
false)
1118 state()->allJobs().append(job);
1121 createNewJobTableRow(job);
1126bool Camera::removeJob(
int index)
1138 if (index < 0 || index >= state()->allJobs().count())
1141 queueTable->removeRow(index);
1142 QJsonArray seqArray = state()->getSequence();
1144 state()->setSequence(seqArray);
1145 emit sequenceChanged(seqArray);
1147 if (state()->allJobs().empty())
1152 state()->removeCapturedFrameCount(job->getSignature(), job->getCompleted());
1154 state()->allJobs().removeOne(job);
1155 if (job == activeJob())
1156 state()->setActiveJob(
nullptr);
1160 if (queueTable->rowCount() == 0)
1161 removeFromQueueB->setEnabled(
false);
1163 if (queueTable->rowCount() == 1)
1165 queueUpB->setEnabled(
false);
1166 queueDownB->setEnabled(
false);
1169 if (index < queueTable->rowCount())
1170 queueTable->selectRow(index);
1171 else if (queueTable->rowCount() > 0)
1172 queueTable->selectRow(queueTable->rowCount() - 1);
1174 if (queueTable->rowCount() == 0)
1176 queueSaveAsB->setEnabled(
false);
1177 queueSaveB->setEnabled(
false);
1178 resetB->setEnabled(
false);
1181 state()->setDirty(
true);
1186bool Camera::modifyJob(
int index)
1194 if (index < 0 || index >= state()->allJobs().count())
1197 queueTable->selectRow(index);
1198 auto modelIndex = queueTable->model()->index(index, 0);
1199 editJob(modelIndex);
1203void Camera::loadSequenceQueue()
1207 "Ekos Sequence Queue (*.esq)");
1211 if (fileURL.
isValid() ==
false)
1214 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1223void Camera::saveSequenceQueue()
1225 QUrl backupCurrent = state()->sequenceURL();
1227 if (state()->sequenceURL().toLocalFile().startsWith(
QLatin1String(
"/tmp/"))
1228 || state()->sequenceURL().toLocalFile().contains(
"/Temp"))
1229 state()->setSequenceURL(
QUrl(
""));
1232 if (state()->dirty() ==
false && !state()->sequenceURL().isEmpty())
1235 if (state()->sequenceURL().isEmpty())
1238 "Save Ekos Sequence Queue"),
1240 "Ekos Sequence Queue (*.esq)"));
1242 if (state()->sequenceURL().isEmpty())
1244 state()->setSequenceURL(backupCurrent);
1250 if (state()->sequenceURL().toLocalFile().endsWith(
QLatin1String(
".esq")) ==
false)
1251 state()->setSequenceURL(
QUrl(
"file:" + state()->sequenceURL().toLocalFile() +
".esq"));
1255 if (state()->sequenceURL().
isValid())
1258 if ((process()->saveSequenceQueue(state()->sequenceURL().toLocalFile(), !m_standAlone)) ==
false)
1260 KSNotification::error(
i18n(
"Failed to save sequence queue"),
i18n(
"Save"));
1264 state()->setDirty(
false);
1268 QString message =
i18n(
"Invalid URL: %1", state()->sequenceURL().url());
1269 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1274void Camera::saveSequenceQueueAs()
1276 state()->setSequenceURL(
QUrl(
""));
1277 saveSequenceQueue();
1280void Camera::updateJobTable(
SequenceJob *job,
bool full)
1285 while (iter.hasNext())
1286 updateJobTable(iter.next(), full);
1291 int row = state()->allJobs().indexOf(job);
1292 if (row >= 0 && row < queueTable->rowCount())
1294 updateRowStyle(job);
1297 status->setText(job->getStatusString());
1298 updateJobTableCountCell(job, count);
1302 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
1305 if (FilterPosCombo->findText(job->getCoreProperty(SequenceJob::SJ_Filter).toString()) >= 0 &&
1306 (captureTypeS->currentIndex() == FRAME_LIGHT || captureTypeS->currentIndex() == FRAME_FLAT
1308 filter->setText(job->getCoreProperty(SequenceJob::SJ_Filter).toString());
1313 exp->
setText(
QString(
"%L1").arg(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f',
1314 captureExposureN->decimals()));
1317 type->setText(isDarkFlat ?
i18n(
"Dark Flat") : CCDFrameTypeNames[job->getFrameType()]);
1320 QPoint binning = job->getCoreProperty(SequenceJob::SJ_Binning).toPoint();
1324 if (job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt() != -1)
1325 iso->
setText(captureISOS->itemText(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt()));
1326 else if (job->getCoreProperty(SequenceJob::SJ_Gain).toDouble() >= 0)
1332 if (job->getCoreProperty(SequenceJob::SJ_Offset).toDouble() >= 0)
1339 if (queueTable->rowCount() > 0)
1341 queueSaveAsB->setEnabled(
true);
1342 queueSaveB->setEnabled(
true);
1343 resetB->setEnabled(
true);
1344 state()->setDirty(
true);
1347 if (queueTable->rowCount() > 1)
1349 queueUpB->setEnabled(
true);
1350 queueDownB->setEnabled(
true);
1356void Camera::updateJobFromUI(
SequenceJob *job, FilenamePreviewType filenamePreview)
1358 job->setCoreProperty(SequenceJob::SJ_Format, captureFormatS->currentText());
1359 job->setCoreProperty(SequenceJob::SJ_Encoding, captureEncodingS->currentText());
1362 job->setISO(captureISOS->currentIndex());
1364 job->setCoreProperty(SequenceJob::SJ_Gain, getGain());
1365 job->setCoreProperty(SequenceJob::SJ_Offset, getOffset());
1367 if (cameraTemperatureN->isEnabled())
1369 job->setCoreProperty(SequenceJob::SJ_EnforceTemperature, cameraTemperatureS->isChecked());
1370 job->setTargetTemperature(cameraTemperatureN->value());
1373 job->setScripts(m_scriptsManager->getScripts());
1374 job->setUploadMode(
static_cast<ISD::Camera::UploadMode
>(fileUploadModeS->currentIndex()));
1377 job->setFlatFieldDuration(m_CalibrationUI->captureCalibrationDurationManual->isChecked() ? DURATION_MANUAL :
1380 int action = CAPTURE_PREACTION_NONE;
1381 if (m_CalibrationUI->captureCalibrationParkMount->isChecked())
1382 action |= CAPTURE_PREACTION_PARK_MOUNT;
1383 if (m_CalibrationUI->captureCalibrationParkDome->isChecked())
1384 action |= CAPTURE_PREACTION_PARK_DOME;
1385 if (m_CalibrationUI->captureCalibrationWall->isChecked())
1387 bool azOk =
false, altOk =
false;
1388 auto wallAz = m_CalibrationUI->azBox->createDms(&azOk);
1389 auto wallAlt = m_CalibrationUI->altBox->createDms(&altOk);
1393 action = (action & ~CAPTURE_PREACTION_PARK_MOUNT) | CAPTURE_PREACTION_WALL;
1395 wallSkyPoint.
setAz(wallAz);
1396 wallSkyPoint.
setAlt(wallAlt);
1397 job->setWallCoord(wallSkyPoint);
1401 if (m_CalibrationUI->captureCalibrationUseADU->isChecked())
1403 job->setCoreProperty(SequenceJob::SJ_TargetADU, m_CalibrationUI->captureCalibrationADUValue->value());
1404 job->setCoreProperty(SequenceJob::SJ_TargetADUTolerance,
1405 m_CalibrationUI->captureCalibrationADUTolerance->value());
1406 job->setCoreProperty(SequenceJob::SJ_SkyFlat, m_CalibrationUI->captureCalibrationSkyFlats->isChecked());
1409 job->setCalibrationPreAction(action);
1411 job->setFrameType(
static_cast<CCDFrameType
>(qMax(0, captureTypeS->currentIndex())));
1413 if (FilterPosCombo->currentIndex() != -1 && (m_standAlone || devices()->filterWheel() !=
nullptr))
1414 job->setTargetFilter(FilterPosCombo->currentIndex() + 1, FilterPosCombo->currentText());
1416 job->setCoreProperty(SequenceJob::SJ_Exposure, captureExposureN->value());
1418 job->setCoreProperty(SequenceJob::SJ_Count, captureCountN->value());
1420 job->setCoreProperty(SequenceJob::SJ_Binning,
QPoint(captureBinHN->value(), captureBinVN->value()));
1423 job->setCoreProperty(SequenceJob::SJ_Delay, captureDelayN->value() * 1000);
1426 job->setCustomProperties(customPropertiesDialog()->getCustomProperties());
1428 job->setCoreProperty(SequenceJob::SJ_ROI,
QRect(captureFrameXN->value(), captureFrameYN->value(),
1429 captureFrameWN->value(),
1430 captureFrameHN->value()));
1431 job->setCoreProperty(SequenceJob::SJ_RemoteDirectory, fileRemoteDirT->text());
1432 job->setCoreProperty(SequenceJob::SJ_LocalDirectory, fileDirectoryT->text());
1433 job->setCoreProperty(SequenceJob::SJ_TargetName, targetNameT->text());
1434 job->setCoreProperty(SequenceJob::SJ_PlaceholderFormat, placeholderFormatT->text());
1435 job->setCoreProperty(SequenceJob::SJ_PlaceholderSuffix, formatSuffixN->value());
1437 job->setCoreProperty(SequenceJob::SJ_DitherPerJobFrequency, m_LimitsUI->guideDitherPerJobFrequency->value());
1439 auto placeholderPath = PlaceholderPath();
1440 placeholderPath.updateFullPrefix(job, placeholderFormatT->text());
1442 QString signature = placeholderPath.generateSequenceFilename(*job,
1443 filenamePreview != FILENAME_REMOTE_PREVIEW,
true, 1,
1444 ".fits",
"",
false,
true);
1445 job->setCoreProperty(SequenceJob::SJ_Signature, signature);
1453 qWarning(KSTARS_EKOS_CAPTURE) <<
"syncGuiToJob with null job.";
1458 const auto roi = job->getCoreProperty(SequenceJob::SJ_ROI).toRect();
1460 captureFormatS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Format).toString());
1461 captureEncodingS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Encoding).toString());
1462 captureExposureN->setValue(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble());
1463 captureBinHN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().x());
1464 captureBinVN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().y());
1465 captureFrameXN->setValue(roi.x());
1466 captureFrameYN->setValue(roi.y());
1467 captureFrameWN->setValue(roi.width());
1468 captureFrameHN->setValue(roi.height());
1469 FilterPosCombo->setCurrentIndex(job->getTargetFilter() - 1);
1470 captureTypeS->setCurrentIndex(job->getFrameType());
1471 captureCountN->setValue(job->getCoreProperty(SequenceJob::SJ_Count).toInt());
1472 captureDelayN->setValue(job->getCoreProperty(SequenceJob::SJ_Delay).toInt() / 1000);
1473 targetNameT->setText(job->getCoreProperty(SequenceJob::SJ_TargetName).toString());
1474 fileDirectoryT->setText(job->getCoreProperty(SequenceJob::SJ_LocalDirectory).toString());
1475 fileUploadModeS->setCurrentIndex(job->getUploadMode());
1476 fileRemoteDirT->setEnabled(fileUploadModeS->currentIndex() != 0);
1477 fileRemoteDirT->setText(job->getCoreProperty(SequenceJob::SJ_RemoteDirectory).toString());
1478 placeholderFormatT->setText(job->getCoreProperty(SequenceJob::SJ_PlaceholderFormat).toString());
1479 formatSuffixN->setValue(job->getCoreProperty(SequenceJob::SJ_PlaceholderSuffix).toUInt());
1482 cameraTemperatureS->setChecked(job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool());
1483 if (job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool())
1484 cameraTemperatureN->setValue(job->getTargetTemperature());
1487 m_LimitsUI->guideDitherPerJobFrequency->setValue(job->getCoreProperty(
1488 SequenceJob::SJ_DitherPerJobFrequency).toInt());
1489 syncLimitSettings();
1492 calibrationB->setEnabled(job->getFrameType() != FRAME_LIGHT);
1493 generateDarkFlatsB->setEnabled(job->getFrameType() != FRAME_LIGHT);
1495 if (job->getFlatFieldDuration() == DURATION_MANUAL)
1496 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1498 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1501 const auto action = job->getCalibrationPreAction();
1502 if (action & CAPTURE_PREACTION_WALL)
1504 m_CalibrationUI->azBox->setText(job->getWallCoord().az().toDMSString());
1505 m_CalibrationUI->altBox->setText(job->getWallCoord().alt().toDMSString());
1507 m_CalibrationUI->captureCalibrationWall->setChecked(action & CAPTURE_PREACTION_WALL);
1508 m_CalibrationUI->captureCalibrationParkMount->setChecked(action & CAPTURE_PREACTION_PARK_MOUNT);
1509 m_CalibrationUI->captureCalibrationParkDome->setChecked(action & CAPTURE_PREACTION_PARK_DOME);
1512 switch (job->getFlatFieldDuration())
1514 case DURATION_MANUAL:
1515 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1519 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1520 m_CalibrationUI->captureCalibrationADUValue->setValue(job->getCoreProperty(SequenceJob::SJ_TargetADU).toUInt());
1521 m_CalibrationUI->captureCalibrationADUTolerance->setValue(job->getCoreProperty(
1522 SequenceJob::SJ_TargetADUTolerance).toUInt());
1523 m_CalibrationUI->captureCalibrationSkyFlats->setChecked(job->getCoreProperty(SequenceJob::SJ_SkyFlat).toBool());
1527 m_scriptsManager->setScripts(job->getScripts());
1530 customPropertiesDialog()->setCustomProperties(job->getCustomProperties());
1533 captureISOS->setCurrentIndex(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt());
1535 double gain = getGain();
1537 captureGainN->setValue(gain);
1539 captureGainN->setValue(GainSpinSpecialValue);
1541 double offset = getOffset();
1543 captureOffsetN->setValue(offset);
1545 captureOffsetN->setValue(OffsetSpinSpecialValue);
1548 generatePreviewFilename();
1550 if (m_RotatorControlPanel)
1552 if (job->getTargetRotation() != Ekos::INVALID_VALUE)
1555 m_RotatorControlPanel->setCameraPA(job->getTargetRotation());
1563 if (Options::alignCheckFrequency() == 0)
1565 targetDriftLabel->setVisible(
false);
1566 targetDrift->setVisible(
false);
1567 targetDriftUnit->setVisible(
false);
1571void Camera::syncFrameType(
const QString &name)
1573 if (!activeCamera() || name != activeCamera()->getDeviceName())
1578 captureTypeS->clear();
1581 captureTypeS->setEnabled(
false);
1584 captureTypeS->setEnabled(
true);
1585 captureTypeS->addItems(frameTypes);
1586 ISD::CameraChip *tChip = devices()->getActiveCamera()->getChip(ISD::CameraChip::PRIMARY_CCD);
1587 captureTypeS->setCurrentIndex(tChip->getFrameType());
1591void Camera::syncCameraInfo()
1593 if (!activeCamera())
1596 const QString timestamp = KStarsData::Instance()->
lt().
toString(
"yyyy-MM-dd hh:mm");
1597 storeTrainKeyString(KEY_TIMESTAMP, timestamp);
1599 if (activeCamera()->hasCooler())
1601 cameraTemperatureS->setEnabled(
true);
1602 cameraTemperatureN->setEnabled(
true);
1604 if (activeCamera()->getPermission(
"CCD_TEMPERATURE") != IP_RO)
1606 double min, max, step;
1607 setTemperatureB->setEnabled(
true);
1608 cameraTemperatureN->setReadOnly(
false);
1609 cameraTemperatureS->setEnabled(
true);
1610 temperatureRegulationB->setEnabled(
true);
1611 activeCamera()->getMinMaxStep(
"CCD_TEMPERATURE",
"CCD_TEMPERATURE_VALUE", &min, &max, &step);
1612 cameraTemperatureN->setMinimum(min);
1613 cameraTemperatureN->setMaximum(max);
1614 cameraTemperatureN->setSingleStep(1);
1615 bool isChecked = activeCamera()->getDriverInfo()->getAuxInfo().value(
QString(
"%1_TC").arg(activeCamera()->getDeviceName()),
1617 cameraTemperatureS->setChecked(isChecked);
1623 isChecked ?
"1" :
"0" } );
1624 storeTrainKey(KEY_TEMPERATURE, temperatureList);
1628 setTemperatureB->setEnabled(
false);
1629 cameraTemperatureN->setReadOnly(
true);
1630 cameraTemperatureS->setEnabled(
false);
1631 cameraTemperatureS->setChecked(
false);
1632 temperatureRegulationB->setEnabled(
false);
1636 storeTrainKey(KEY_TEMPERATURE, temperatureList);
1639 double temperature = 0;
1640 if (activeCamera()->getTemperature(&temperature))
1642 temperatureOUT->setText(
QString(
"%L1º").arg(temperature, 0,
'f', 1));
1643 if (cameraTemperatureN->cleanText().isEmpty())
1644 cameraTemperatureN->setValue(temperature);
1649 cameraTemperatureS->setEnabled(
false);
1650 cameraTemperatureN->setEnabled(
false);
1651 temperatureRegulationB->setEnabled(
false);
1652 cameraTemperatureN->clear();
1653 temperatureOUT->clear();
1654 setTemperatureB->setEnabled(
false);
1657 auto isoList = devices()->getActiveChip()->getISOList();
1658 captureISOS->blockSignals(
true);
1659 captureISOS->setEnabled(
false);
1660 captureISOS->clear();
1663 if (isoList.isEmpty())
1665 captureISOS->setEnabled(
false);
1666 if (settings().contains(KEY_ISOS))
1668 settings().remove(KEY_ISOS);
1669 m_DebounceTimer.
start();
1671 if (settings().contains(KEY_INDEX))
1673 settings().remove(KEY_INDEX);
1674 m_DebounceTimer.
start();
1679 captureISOS->setEnabled(
true);
1680 captureISOS->addItems(isoList);
1681 const int isoIndex = devices()->getActiveChip()->getISOIndex();
1682 captureISOS->setCurrentIndex(isoIndex);
1685 storeTrainKey(KEY_ISOS, isoList);
1686 storeTrainKeyString(KEY_INDEX,
QString(
"%1").arg(isoIndex));
1690 double pixelX = 0, pixelY = 0;
1691 bool rc = devices()->getActiveChip()->getImageInfo(w, h, pixelX, pixelY, bbp);
1692 bool isModelInDB = state()->isModelinDSLRInfo(
QString(activeCamera()->getDeviceName()));
1695 if (rc ==
true && (pixelX == 0.0 || pixelY == 0.0 || isModelInDB ==
false))
1699 if (isModelInDB ==
false)
1706 process()->syncDSLRToTargetChip(model);
1710 captureISOS->blockSignals(
false);
1713 if (activeCamera()->hasGain())
1715 double min, max, step, value, targetCustomGain;
1716 activeCamera()->getGainMinMaxStep(&min, &max, &step);
1719 GainSpinSpecialValue = min - step;
1720 captureGainN->setRange(GainSpinSpecialValue, max);
1721 captureGainN->setSpecialValueText(
i18n(
"--"));
1722 captureGainN->setEnabled(
true);
1723 captureGainN->setSingleStep(step);
1724 activeCamera()->getGain(&value);
1727 targetCustomGain = getGain();
1731 if (targetCustomGain > 0)
1732 captureGainN->setValue(targetCustomGain);
1734 captureGainN->setValue(GainSpinSpecialValue);
1736 captureGainN->setReadOnly(activeCamera()->getGainPermission() == IP_RO);
1740 if (captureGainN->value() != GainSpinSpecialValue)
1741 setGain(captureGainN->value());
1748 captureGainN->setEnabled(
false);
1749 currentGainLabel->clear();
1753 if (activeCamera()->hasOffset())
1755 double min, max, step, value, targetCustomOffset;
1756 activeCamera()->getOffsetMinMaxStep(&min, &max, &step);
1759 OffsetSpinSpecialValue = min - step;
1760 captureOffsetN->setRange(OffsetSpinSpecialValue, max);
1761 captureOffsetN->setSpecialValueText(
i18n(
"--"));
1762 captureOffsetN->setEnabled(
true);
1763 captureOffsetN->setSingleStep(step);
1764 activeCamera()->getOffset(&value);
1767 targetCustomOffset = getOffset();
1771 if (targetCustomOffset > 0)
1772 captureOffsetN->setValue(targetCustomOffset);
1774 captureOffsetN->setValue(OffsetSpinSpecialValue);
1776 captureOffsetN->setReadOnly(activeCamera()->getOffsetPermission() == IP_RO);
1780 if (captureOffsetN->value() != OffsetSpinSpecialValue)
1781 setOffset(captureOffsetN->value());
1788 captureOffsetN->setEnabled(
false);
1789 currentOffsetLabel->clear();
1793void Camera::createNewJobTableRow(
SequenceJob *job)
1795 int currentRow = queueTable->rowCount();
1796 queueTable->insertRow(currentRow);
1832 queueTable->setItem(currentRow, JOBTABLE_COL_STATUS, status);
1833 queueTable->setItem(currentRow, JOBTABLE_COL_FILTER, filter);
1834 queueTable->setItem(currentRow, JOBTABLE_COL_COUNTS, count);
1835 queueTable->setItem(currentRow, JOBTABLE_COL_EXP, exp);
1836 queueTable->setItem(currentRow, JOBTABLE_COL_TYPE, type);
1837 queueTable->setItem(currentRow, JOBTABLE_COL_BINNING, bin);
1838 queueTable->setItem(currentRow, JOBTABLE_COL_ISO, iso);
1839 queueTable->setItem(currentRow, JOBTABLE_COL_OFFSET, offset);
1842 updateJobTable(job,
true);
1845 QJsonObject jsonJob = createJsonJob(job, currentRow);
1846 state()->getSequence().append(jsonJob);
1847 emit sequenceChanged(state()->getSequence());
1849 removeFromQueueB->setEnabled(
true);
1858 int row = state()->allJobs().indexOf(job);
1859 if (row >= 0 && row < queueTable->rowCount())
1861 updateCellStyle(queueTable->item(row, JOBTABLE_COL_STATUS), job->getStatus() == JOB_BUSY);
1862 updateCellStyle(queueTable->item(row, JOBTABLE_COL_FILTER), job->getStatus() == JOB_BUSY);
1863 updateCellStyle(queueTable->item(row, JOBTABLE_COL_COUNTS), job->getStatus() == JOB_BUSY);
1864 updateCellStyle(queueTable->item(row, JOBTABLE_COL_EXP), job->getStatus() == JOB_BUSY);
1865 updateCellStyle(queueTable->item(row, JOBTABLE_COL_TYPE), job->getStatus() == JOB_BUSY);
1866 updateCellStyle(queueTable->item(row, JOBTABLE_COL_BINNING), job->getStatus() == JOB_BUSY);
1867 updateCellStyle(queueTable->item(row, JOBTABLE_COL_ISO), job->getStatus() == JOB_BUSY);
1868 updateCellStyle(queueTable->item(row, JOBTABLE_COL_OFFSET), job->getStatus() == JOB_BUSY);
1874 if (cell ==
nullptr)
1878 font.setBold(active);
1879 font.setItalic(active);
1883bool Camera::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget *widget)
1896 const int value = settings[key].toInt(&ok);
1905 const double value = settings[key].toDouble(&ok);
1910 if (pDSB == captureGainN)
1912 if (captureGainN->value() != GainSpinSpecialValue)
1913 setGain(captureGainN->value());
1917 else if (pDSB == captureOffsetN)
1919 if (captureOffsetN->value() != OffsetSpinSpecialValue)
1920 setOffset(captureOffsetN->value());
1929 const bool value = settings[key].toBool();
1936 const bool value = settings[key].toBool();
1938 pRadioButton->
click();
1944 const QString value = settings[key].toString();
1956 const bool value = settings[key].toBool();
1958 pRadioButton->
click();
1963 const auto value = settings[key].toString();
1966 if (pLineEdit == fileRemoteDirT)
1967 generatePreviewFilename();
1974void Camera::moveJob(
bool up)
1976 int currentRow = queueTable->currentRow();
1977 int destinationRow =
up ? currentRow - 1 : currentRow + 1;
1979 int columnCount = queueTable->columnCount();
1981 if (currentRow < 0 || destinationRow < 0 || destinationRow >= queueTable->rowCount())
1984 for (
int i = 0; i < columnCount; i++)
1989 queueTable->setItem(destinationRow, i, selectedLine);
1990 queueTable->setItem(currentRow, i, counterpart);
1993 SequenceJob * job = state()->allJobs().takeAt(currentRow);
1995 state()->allJobs().removeOne(job);
1996 state()->allJobs().insert(destinationRow, job);
1998 QJsonArray seqArray = state()->getSequence();
1999 QJsonObject currentJob = seqArray[currentRow].toObject();
2000 seqArray.
replace(currentRow, seqArray[destinationRow]);
2001 seqArray.
replace(destinationRow, currentJob);
2002 emit sequenceChanged(seqArray);
2004 queueTable->selectRow(destinationRow);
2006 state()->setDirty(
true);
2009void Camera::removeJobFromQueue()
2011 int currentRow = queueTable->currentRow();
2014 currentRow = queueTable->rowCount() - 1;
2016 removeJob(currentRow);
2019 if (queueTable->rowCount() == 0)
2022 if (currentRow > queueTable->rowCount())
2023 queueTable->selectRow(queueTable->rowCount() - 1);
2025 queueTable->selectRow(currentRow);
2028void Camera::saveFITSDirectory()
2038void Camera::updateCaptureFormats()
2042 captureTypeS->clear();
2045 captureTypeS->setEnabled(
false);
2048 captureTypeS->setEnabled(
true);
2049 captureTypeS->addItems(frameTypes);
2050 captureTypeS->setCurrentIndex(devices()->getActiveChip()->getFrameType());
2054 captureFormatS->blockSignals(
true);
2055 captureFormatS->clear();
2056 const auto list = activeCamera()->getCaptureFormats();
2057 captureFormatS->addItems(list);
2058 storeTrainKey(KEY_FORMATS, list);
2060 captureFormatS->setCurrentText(activeCamera()->getCaptureFormat());
2061 captureFormatS->blockSignals(
false);
2064 captureEncodingS->blockSignals(
true);
2065 captureEncodingS->clear();
2066 captureEncodingS->addItems(activeCamera()->getEncodingFormats());
2067 captureEncodingS->setCurrentText(activeCamera()->getEncodingFormat());
2068 captureEncodingS->blockSignals(
false);
2071void Camera::updateHFRCheckAlgo()
2074 const bool threshold = (m_LimitsUI->hFRCheckAlgorithm->currentIndex() != HFR_CHECK_FIXED);
2075 m_LimitsUI->hFRThresholdPercentage->setEnabled(threshold);
2076 m_LimitsUI->limitFocusHFRThresholdLabel->setEnabled(threshold);
2077 m_LimitsUI->limitFocusHFRPercentLabel->setEnabled(threshold);
2078 state()->updateHFRThreshold();
2081void Camera::clearAutoFocusHFR()
2083 if (Options::hFRCheckAlgorithm() == HFR_CHECK_FIXED)
2086 m_LimitsUI->hFRDeviation->setValue(0);
2096void Camera::clearCameraConfiguration()
2102 devices()->getActiveCamera()->setConfig(PURGE_CONFIG);
2103 KStarsData::Instance()->
userdb()->DeleteDSLRInfo(devices()->getActiveCamera()->getDeviceName());
2105 QStringList shutterfulCCDs = Options::shutterfulCCDs();
2106 QStringList shutterlessCCDs = Options::shutterlessCCDs();
2109 if (shutterfulCCDs.
contains(devices()->getActiveCamera()->getDeviceName()))
2111 shutterfulCCDs.
removeOne(devices()->getActiveCamera()->getDeviceName());
2112 Options::setShutterfulCCDs(shutterfulCCDs);
2114 if (shutterlessCCDs.
contains(devices()->getActiveCamera()->getDeviceName()))
2116 shutterlessCCDs.
removeOne(devices()->getActiveCamera()->getDeviceName());
2117 Options::setShutterlessCCDs(shutterlessCCDs);
2121 if (captureISOS && captureISOS->count() > 0)
2127 KSMessageBox::Instance()->questionYesNo(
i18n(
"Reset %1 configuration to default?",
2128 devices()->getActiveCamera()->getDeviceName()),
2129 i18n(
"Confirmation"), 30);
2132void Camera::editFilterName()
2137 for (
int index = 0; index < FilterPosCombo->count(); index++)
2138 labels << FilterPosCombo->itemText(index);
2140 if (editFilterNameInternal(labels, newLabels))
2142 FilterPosCombo->clear();
2143 FilterPosCombo->addItems(newLabels);
2148 if (devices()->filterWheel() ==
nullptr || state()->getCurrentFilterPosition() < 1)
2151 QStringList labels = filterManager()->getFilterLabels();
2153 if (editFilterNameInternal(labels, newLabels))
2154 filterManager()->setFilterNames(newLabels);
2165 for (uint8_t i = 0; i < labels.
count(); i++)
2167 QLabel *existingLabel =
new QLabel(
QString(
"%1. <b>%2</b>").arg(i + 1).arg(labels[i]), &filterDialog);
2169 newLabelEdits.
append(newLabel);
2170 formLayout->
addRow(existingLabel, newLabel);
2173 QString title = m_standAlone ?
2174 "Edit Filter Names" : devices()->filterWheel()->getDeviceName();
2185 for (uint8_t i = 0; i < labels.
count(); i++)
2186 results << newLabelEdits[i]->text();
2187 newLabels = results;
2193void Camera::loadGlobalSettings()
2198 QVariantMap settings;
2202 if (oneWidget->objectName() ==
"opticalTrainCombo")
2205 key = oneWidget->objectName();
2206 value = Options::self()->property(key.
toLatin1());
2207 if (value.
isValid() && oneWidget->count() > 0)
2209 oneWidget->setCurrentText(value.
toString());
2210 settings[key] = value;
2213 QCDEBUG <<
"Option" << key <<
"not found!";
2219 key = oneWidget->objectName();
2220 value = Options::self()->property(key.
toLatin1());
2223 oneWidget->setValue(value.
toDouble());
2224 settings[key] = value;
2227 QCDEBUG <<
"Option" << key <<
"not found!";
2233 key = oneWidget->objectName();
2234 value = Options::self()->property(key.
toLatin1());
2237 oneWidget->setValue(value.
toInt());
2238 settings[key] = value;
2241 QCDEBUG <<
"Option" << key <<
"not found!";
2247 key = oneWidget->objectName();
2248 value = Options::self()->property(key.
toLatin1());
2251 oneWidget->setChecked(value.
toBool());
2252 settings[key] = value;
2255 QCDEBUG <<
"Option" << key <<
"not found!";
2261 if (oneWidget->isCheckable())
2263 key = oneWidget->objectName();
2264 value = Options::self()->property(key.
toLatin1());
2267 oneWidget->setChecked(value.
toBool());
2268 settings[key] = value;
2271 QCDEBUG <<
"Option" << key <<
"not found!";
2278 key = oneWidget->objectName();
2279 value = Options::self()->property(key.
toLatin1());
2282 oneWidget->setChecked(value.
toBool());
2283 settings[key] = value;
2290 if (oneWidget->objectName() ==
"qt_spinbox_lineedit" || oneWidget->isReadOnly())
2292 key = oneWidget->objectName();
2293 value = Options::self()->property(key.
toLatin1());
2296 oneWidget->setText(value.
toString());
2297 settings[key] = value;
2300 m_GlobalSettings = settings;
2301 setSettings(settings);
2304bool Camera::checkUploadPaths(FilenamePreviewType filenamePreview)
2307 if (filenamePreview != FILENAME_NOT_PREVIEW)
2310 if (fileUploadModeS->currentIndex() != ISD::Camera::UPLOAD_CLIENT && fileRemoteDirT->text().isEmpty())
2312 KSNotification::error(
i18n(
"You must set remote directory for Local & Both modes."));
2316 if (fileUploadModeS->currentIndex() != ISD::Camera::UPLOAD_LOCAL && fileDirectoryT->text().isEmpty())
2318 KSNotification::error(
i18n(
"You must set local directory for Client & Both modes."));
2331 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
2332 jsonJob.
insert(
"Filter", FilterPosCombo->itemText(job->getTargetFilter() - 1));
2333 jsonJob.
insert(
"Count", queueTable->item(currentRow, JOBTABLE_COL_COUNTS)->text());
2334 jsonJob.
insert(
"Exp", queueTable->item(currentRow, JOBTABLE_COL_EXP)->text());
2335 jsonJob.
insert(
"Type", isDarkFlat ?
i18n(
"Dark Flat") : queueTable->item(currentRow, JOBTABLE_COL_TYPE)->text());
2336 jsonJob.
insert(
"Bin", queueTable->item(currentRow, JOBTABLE_COL_BINNING)->text());
2337 jsonJob.
insert(
"ISO/Gain", queueTable->item(currentRow, JOBTABLE_COL_ISO)->text());
2338 jsonJob.
insert(
"Offset", queueTable->item(currentRow, JOBTABLE_COL_OFFSET)->text());
2339 jsonJob.
insert(
"Encoding", job->getCoreProperty(SequenceJob::SJ_Encoding).toJsonValue());
2340 jsonJob.
insert(
"Format", job->getCoreProperty(SequenceJob::SJ_Format).toJsonValue());
2341 jsonJob.
insert(
"Temperature", job->getTargetTemperature());
2342 jsonJob.
insert(
"EnforceTemperature", job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toJsonValue());
2343 jsonJob.
insert(
"DitherPerJobFrequency", job->getCoreProperty(SequenceJob::SJ_DitherPerJobFrequency).toJsonValue());
2348void Camera::generatePreviewFilename()
2350 if (state()->isCaptureRunning() ==
false)
2352 placeholderFormatT->setToolTip(previewFilename( FILENAME_LOCAL_PREVIEW ));
2353 emit newLocalPreview(placeholderFormatT->toolTip());
2355 if (fileUploadModeS->currentIndex() != 0)
2356 fileRemoteDirT->setToolTip(previewFilename( FILENAME_REMOTE_PREVIEW ));
2360QString Camera::previewFilename(FilenamePreviewType previewType)
2366 if (previewType == FILENAME_LOCAL_PREVIEW)
2368 if(!fileDirectoryT->text().endsWith(separator) && !placeholderFormatT->text().startsWith(separator))
2369 placeholderFormatT->setText(separator + placeholderFormatT->text());
2370 m_format = fileDirectoryT->text() + placeholderFormatT->text() + formatSuffixN->prefix() +
2371 formatSuffixN->cleanText();
2373 else if (previewType == FILENAME_REMOTE_PREVIEW)
2374 m_format = fileRemoteDirT->text();
2382 else if (state()->sequenceURL().toLocalFile().isEmpty() && m_format.
contains(
"%f"))
2383 previewText = (
"Save the sequence file to show filename preview");
2387 SequenceJob *m_job = createJob(SequenceJob::JOBTYPE_PREVIEW, previewType);
2388 if (m_job ==
nullptr)
2392 if (state()->sequenceURL().toLocalFile().isEmpty())
2398 previewSeq = state()->sequenceURL().toLocalFile();
2399 auto m_placeholderPath = PlaceholderPath(previewSeq);
2402 if (captureEncodingS->currentText() ==
"FITS")
2403 extension =
".fits";
2404 else if (captureEncodingS->currentText() ==
"XISF")
2405 extension =
".xisf";
2407 extension =
".[NATIVE]";
2408 previewText = m_placeholderPath.generateSequenceFilename(*m_job, previewType == FILENAME_LOCAL_PREVIEW,
true, 1,
2409 extension,
"",
false);
2412 m_job->deleteLater();
2416 if (previewType == FILENAME_REMOTE_PREVIEW)
2417 previewText.
replace(separator,
"/");
2424 countCell->
setText(
QString(
"%L1/%L2").arg(job->getCompleted()).
arg(job->getCoreProperty(SequenceJob::SJ_Count).toInt()));
2427void Camera::addDSLRInfo(
const QString &model, uint32_t maxW, uint32_t maxH,
double pixelW,
double pixelH)
2430 auto pos = std::find_if(state()->DSLRInfos().
begin(), state()->DSLRInfos().
end(), [model](
const auto & oneDSLRInfo)
2432 return (oneDSLRInfo[
"Model"] == model);
2435 if (
pos != state()->DSLRInfos().
end())
2437 KStarsData::Instance()->
userdb()->DeleteDSLRInfo(model);
2438 state()->DSLRInfos().removeOne(*
pos);
2442 oneDSLRInfo[
"Model"] = model;
2443 oneDSLRInfo[
"Width"] = maxW;
2444 oneDSLRInfo[
"Height"] = maxH;
2445 oneDSLRInfo[
"PixelW"] = pixelW;
2446 oneDSLRInfo[
"PixelH"] = pixelH;
2448 KStarsData::Instance()->
userdb()->AddDSLRInfo(oneDSLRInfo);
2449 KStarsData::Instance()->
userdb()->GetAllDSLRInfos(state()->DSLRInfos());
2451 updateFrameProperties();
2452 process()->resetFrame();
2453 process()->syncDSLRToTargetChip(model);
2456 if (m_DSLRInfoDialog)
2457 m_DSLRInfoDialog.reset();
2462 process()->startNextPendingJob();
2465void Camera::stop(CaptureState targetState)
2467 process()->stopCapturing(targetState);
2472 process()->pauseCapturing();
2473 updateStartButtons(
false,
true);
2476void Camera::toggleSequence()
2478 const CaptureState capturestate = state()->getCaptureState();
2480 updateStartButtons(
true,
false);
2482 process()->toggleSequence();
2485void Camera::toggleVideo(
bool enabled)
2487 process()->toggleVideo(
enabled);
2490void Camera::restartCamera(
const QString &name)
2492 process()->restartCamera(name);
2495void Camera::cullToDSLRLimits()
2497 QString model(devices()->getActiveCamera()->getDeviceName());
2500 auto pos = std::find_if(state()->DSLRInfos().
begin(),
2503 return (oneDSLRInfo[
"Model"] == model);
2506 if (
pos != state()->DSLRInfos().
end())
2508 if (captureFrameWN->maximum() == 0 || captureFrameWN->maximum() > (*
pos)[
"Width"].toInt())
2510 captureFrameWN->setValue((*
pos)[
"Width"].toInt());
2511 captureFrameWN->setMaximum((*
pos)[
"Width"].toInt());
2514 if (captureFrameHN->maximum() == 0 || captureFrameHN->maximum() > (*
pos)[
"Height"].toInt())
2516 captureFrameHN->setValue((*
pos)[
"Height"].toInt());
2517 captureFrameHN->setMaximum((*
pos)[
"Height"].toInt());
2522void Camera::resetFrameToZero()
2524 captureFrameXN->setMinimum(0);
2525 captureFrameXN->setMaximum(0);
2526 captureFrameXN->setValue(0);
2528 captureFrameYN->setMinimum(0);
2529 captureFrameYN->setMaximum(0);
2530 captureFrameYN->setValue(0);
2532 captureFrameWN->setMinimum(0);
2533 captureFrameWN->setMaximum(0);
2534 captureFrameWN->setValue(0);
2536 captureFrameHN->setMinimum(0);
2537 captureFrameHN->setMaximum(0);
2538 captureFrameHN->setValue(0);
2541void Camera::updateFrameProperties(
int reset)
2543 if (!devices()->getActiveCamera())
2546 int binx = 1, biny = 1;
2547 double min, max, step;
2548 int xstep = 0, ystep = 0;
2551 QString exposureProp = state()->useGuideHead() ?
QString(
"GUIDER_EXPOSURE") :
QString(
"CCD_EXPOSURE");
2552 QString exposureElem = state()->useGuideHead() ?
QString(
"GUIDER_EXPOSURE_VALUE") :
2553 QString(
"CCD_EXPOSURE_VALUE");
2554 devices()->setActiveChip(state()->useGuideHead() ?
2555 devices()->getActiveCamera()->getChip(
2556 ISD::CameraChip::GUIDE_CCD) :
2557 devices()->getActiveCamera()->getChip(ISD::CameraChip::PRIMARY_CCD));
2559 captureFrameWN->setEnabled(devices()->getActiveChip()->canSubframe());
2560 captureFrameHN->setEnabled(devices()->getActiveChip()->canSubframe());
2561 captureFrameXN->setEnabled(devices()->getActiveChip()->canSubframe());
2562 captureFrameYN->setEnabled(devices()->getActiveChip()->canSubframe());
2564 captureBinHN->setEnabled(devices()->getActiveChip()->canBin());
2565 captureBinVN->setEnabled(devices()->getActiveChip()->canBin());
2568 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 <<
2569 10 << 20 << 30 << 40 << 50 << 60 << 120 << 180 << 300 << 600 << 900 << 1200 << 1800;
2571 if (devices()->getActiveCamera()->getMinMaxStep(exposureProp, exposureElem, &min, &max, &step))
2574 captureExposureN->setDecimals(6);
2576 captureExposureN->setDecimals(3);
2577 for(
int i = 0; i < exposureValues.
count(); i++)
2579 double value = exposureValues.
at(i);
2580 if(value < min || value > max)
2588 exposureValues.
append(max);
2591 captureExposureN->setRecommendedValues(exposureValues);
2592 state()->setExposureRange(exposureValues.
first(), exposureValues.
last());
2594 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"WIDTH", &min, &max, &step))
2603 xstep =
static_cast<int>(max * 0.05);
2605 xstep =
static_cast<int>(step);
2607 if (min >= 0 && max > 0)
2609 captureFrameWN->setMinimum(
static_cast<int>(min));
2610 captureFrameWN->setMaximum(
static_cast<int>(max));
2611 captureFrameWN->setSingleStep(xstep);
2617 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"HEIGHT", &min, &max, &step))
2626 ystep =
static_cast<int>(max * 0.05);
2628 ystep =
static_cast<int>(step);
2630 if (min >= 0 && max > 0)
2632 captureFrameHN->setMinimum(
static_cast<int>(min));
2633 captureFrameHN->setMaximum(
static_cast<int>(max));
2634 captureFrameHN->setSingleStep(ystep);
2640 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"X", &min, &max, &step))
2651 if (min >= 0 && max > 0)
2653 captureFrameXN->setMinimum(
static_cast<int>(min));
2654 captureFrameXN->setMaximum(
static_cast<int>(max));
2655 captureFrameXN->setSingleStep(
static_cast<int>(step));
2661 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"Y", &min, &max, &step))
2672 if (min >= 0 && max > 0)
2674 captureFrameYN->setMinimum(
static_cast<int>(min));
2675 captureFrameYN->setMaximum(
static_cast<int>(max));
2676 captureFrameYN->setSingleStep(
static_cast<int>(step));
2683 if (state()->useGuideHead() ==
false)
2686 const QString ccdGainKeyword = devices()->getActiveCamera()->getProperty(
"CCD_GAIN") ?
"CCD_GAIN" :
"CCD_CONTROLS";
2687 storeTrainKeyString(KEY_GAIN_KWD, ccdGainKeyword);
2689 const QString ccdOffsetKeyword = devices()->getActiveCamera()->getProperty(
"CCD_OFFSET") ?
"CCD_OFFSET" :
"CCD_CONTROLS";
2690 storeTrainKeyString(KEY_OFFSET_KWD, ccdOffsetKeyword);
2692 if (reset == 1 || state()->frameSettings().contains(devices()->getActiveChip()) ==
false)
2694 QVariantMap settings;
2698 settings[
"w"] = captureFrameWN->maximum();
2699 settings[
"h"] = captureFrameHN->maximum();
2700 settings[
"binx"] = captureBinHN->value();
2701 settings[
"biny"] = captureBinVN->value();
2703 state()->frameSettings()[devices()->getActiveChip()] = settings;
2705 else if (reset == 2 && state()->frameSettings().contains(devices()->getActiveChip()))
2707 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2710 x = settings[
"x"].toInt();
2711 y = settings[
"y"].toInt();
2712 w = settings[
"w"].toInt();
2713 h = settings[
"h"].toInt();
2716 x = qBound(captureFrameXN->minimum(),
x, captureFrameXN->maximum() - 1);
2717 y = qBound(captureFrameYN->minimum(),
y, captureFrameYN->maximum() - 1);
2718 w = qBound(captureFrameWN->minimum(), w, captureFrameWN->maximum());
2719 h = qBound(captureFrameHN->minimum(), h, captureFrameHN->maximum());
2725 settings[
"binx"] = captureBinHN->value();
2726 settings[
"biny"] = captureBinVN->value();
2728 state()->frameSettings()[devices()->getActiveChip()] = settings;
2731 if (state()->frameSettings().contains(devices()->getActiveChip()))
2733 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2734 int x = settings[
"x"].toInt();
2735 int y = settings[
"y"].toInt();
2736 int w = settings[
"w"].toInt();
2737 int h = settings[
"h"].toInt();
2739 if (devices()->getActiveChip()->canBin())
2741 devices()->getActiveChip()->getMaxBin(&binx, &biny);
2742 captureBinHN->setMaximum(binx);
2743 captureBinVN->setMaximum(biny);
2745 captureBinHN->setValue(settings[
"binx"].toInt());
2746 captureBinVN->setValue(settings[
"biny"].toInt());
2750 captureBinHN->setValue(1);
2751 captureBinVN->setValue(1);
2755 captureFrameXN->setValue(
x);
2757 captureFrameYN->setValue(
y);
2759 captureFrameWN->setValue(w);
2761 captureFrameHN->setValue(h);
2767void Camera::setGain(
double value)
2771 setStandAloneGain(value);
2774 if (!devices()->getActiveCamera())
2778 process()->updateGain(value, customProps);
2779 customPropertiesDialog()->setCustomProperties(customProps);
2783double Camera::getGain()
2785 return devices()->cameraGain(customPropertiesDialog()->getCustomProperties());
2788void Camera::setOffset(
double value)
2792 setStandAloneOffset(value);
2795 if (!devices()->getActiveCamera())
2800 process()->updateOffset(value, customProps);
2801 customPropertiesDialog()->setCustomProperties(customProps);
2804double Camera::getOffset()
2806 return devices()->cameraOffset(customPropertiesDialog()->getCustomProperties());
2809void Camera::setRotator(
QString name)
2813 rotatorB->setEnabled(
false);
2814 if (Rotator && !m_RotatorControlPanel.
isNull())
2815 m_RotatorControlPanel->close();
2820 Manager::Instance()->getRotatorController(name, m_RotatorControlPanel);
2821 m_RotatorControlPanel->initRotator(opticalTrainCombo->currentText(), devices().data(),
2825 m_RotatorControlPanel->show();
2826 m_RotatorControlPanel->raise();
2828 rotatorB->setEnabled(
true);
2830 else if (Options::astrometryUseRotator())
2832 RotatorUtils::Instance()->initRotatorUtils(opticalTrainCombo->currentText());
2836void Camera::setMaximumGuidingDeviation(
bool enable,
double value)
2838 m_LimitsUI->enforceGuideDeviation->setChecked(enable);
2840 m_LimitsUI->guideDeviation->setValue(value);
2843void Camera::setInSequenceFocus(
bool enable,
double HFR)
2845 m_LimitsUI->enforceAutofocusHFR->setChecked(enable);
2847 m_LimitsUI->hFRDeviation->setValue(HFR);
2850bool Camera::loadSequenceQueue(
const QString &fileURL,
QString targetName)
2852 QFile sFile(fileURL);
2855 QString message =
i18n(
"Unable to open file %1", fileURL);
2856 KSNotification::sorry(message,
i18n(
"Could Not Open File"));
2860 state()->clearCapturedFramesMap();
2861 clearSequenceQueue();
2864 const bool result = process()->loadSequenceQueue(fileURL, targetName, !m_standAlone);
2866 if (result ==
false)
2870 setObserverName(state()->observerName());
2873 if (state()->allJobs().
size() > 0)
2874 syncGUIToJob(state()->allJobs().first());
2877 queueSaveB->setToolTip(
"Save to " + sFile.fileName());
2882bool Camera::saveSequenceQueue(
const QString &path)
2885 return process()->saveSequenceQueue(path);
2888void Camera::updateCameraStatus(CaptureState status)
2891 emit newStatus(status, opticalTrain(), cameraId());
2894void Camera::clearSequenceQueue()
2896 state()->setActiveJob(
nullptr);
2897 while (queueTable->rowCount() > 0)
2898 queueTable->removeRow(0);
2899 qDeleteAll(state()->allJobs());
2900 state()->allJobs().clear();
2902 while (state()->getSequence().count())
2903 state()->getSequence().pop_back();
2904 emit sequenceChanged(state()->getSequence());
2907QVariantMap Camera::getAllSettings()
const
2909 QVariantMap settings;
2915 auto name = oneWidget->objectName();
2916 if (name ==
"qt_spinbox_lineedit")
2918 settings.insert(name, oneWidget->text());
2923 settings.insert(oneWidget->objectName(), oneWidget->currentText());
2927 settings.insert(oneWidget->objectName(), oneWidget->value());
2931 settings.insert(oneWidget->objectName(), oneWidget->value());
2935 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
2939 if (oneWidget->isCheckable())
2940 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
2944 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
2949void Camera::setAllSettings(
const QVariantMap &settings,
const QVariantMap *standAloneSettings)
2953 disconnectSyncSettings();
2955 for (
auto &name : settings.keys())
2961 syncControl(settings, name, comboBox);
2969 syncControl(settings, name, doubleSpinBox);
2977 syncControl(settings, name, spinBox);
2985 syncControl(settings, name, checkbox);
2991 if (groupbox && groupbox->isCheckable())
2993 syncControl(settings, name, groupbox);
3001 syncControl(settings, name, radioButton);
3009 syncControl(settings, name, lineEdit);
3015 for (
auto &key : settings.keys())
3017 auto value = settings[key];
3019 Options::self()->setProperty(key.
toLatin1(), value);
3021 m_settings[key] = value;
3022 m_GlobalSettings[key] = value;
3025 if (standAloneSettings && standAloneSettings->size() > 0)
3027 for (
const auto &k : standAloneSettings->keys())
3028 m_settings[k] = (*standAloneSettings)[k];
3031 emit settingsUpdated(getAllSettings());
3036 const int id = OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText());
3037 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3038 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
3039 Options::setCaptureTrainID(
id);
3042 connectSyncSettings();
3045void Camera::setupOpticalTrainManager()
3047 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Camera::refreshOpticalTrain);
3050 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
3054 ProfileSettings::Instance()->setOneSetting(ProfileSettings::CaptureOpticalTrain,
3055 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
3056 refreshOpticalTrain();
3057 emit trainChanged();
3061void Camera::refreshOpticalTrain()
3063 opticalTrainCombo->blockSignals(
true);
3064 opticalTrainCombo->clear();
3065 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
3066 trainB->setEnabled(
true);
3068 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3069 if (m_standAlone || trainID.
isValid())
3071 auto id = m_standAlone ? Options::captureTrainID() : trainID.toUInt();
3072 Options::setCaptureTrainID(
id);
3075 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
3077 qCWarning(KSTARS_EKOS_CAPTURE) <<
"Optical train doesn't exist for id" << id;
3078 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
3081 auto name = OpticalTrainManager::Instance()->name(
id);
3083 opticalTrainCombo->setCurrentText(name);
3085 process()->refreshOpticalTrain(name);
3091 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3092 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
3093 if (settings.isValid())
3095 auto map = settings.toJsonObject().toVariantMap();
3096 if (map != m_settings)
3098 QVariantMap standAloneSettings = copyStandAloneSettings(m_settings);
3100 setAllSettings(map, &standAloneSettings);
3104 setSettings(m_GlobalSettings);
3107 opticalTrainCombo->blockSignals(
false);
3110void Camera::selectOpticalTrain(
QString name)
3112 opticalTrainCombo->setCurrentText(name);
3115void Camera::syncLimitSettings()
3117 m_LimitsUI->enforceStartGuiderDrift->setChecked(Options::enforceStartGuiderDrift());
3118 m_LimitsUI->startGuideDeviation->setValue(Options::startGuideDeviation());
3119 m_LimitsUI->enforceGuideDeviation->setChecked(Options::enforceGuideDeviation());
3120 m_LimitsUI->guideDeviation->setValue(Options::guideDeviation());
3121 m_LimitsUI->guideDeviationReps->setValue(
static_cast<int>(Options::guideDeviationReps()));
3122 m_LimitsUI->enforceAutofocusHFR->setChecked(Options::enforceAutofocusHFR());
3123 m_LimitsUI->hFRThresholdPercentage->setValue(Options::hFRThresholdPercentage());
3124 m_LimitsUI->hFRDeviation->setValue(Options::hFRDeviation());
3125 m_LimitsUI->inSequenceCheckFrames->setValue(Options::inSequenceCheckFrames());
3126 m_LimitsUI->hFRCheckAlgorithm->setCurrentIndex(Options::hFRCheckAlgorithm());
3127 m_LimitsUI->enforceAutofocusOnTemperature->setChecked(Options::enforceAutofocusOnTemperature());
3128 m_LimitsUI->maxFocusTemperatureDelta->setValue(Options::maxFocusTemperatureDelta());
3129 m_LimitsUI->enforceRefocusEveryN->setChecked(Options::enforceRefocusEveryN());
3130 m_LimitsUI->refocusEveryN->setValue(
static_cast<int>(Options::refocusEveryN()));
3131 m_LimitsUI->refocusAfterMeridianFlip->setChecked(Options::refocusAfterMeridianFlip());
3134void Camera::settleSettings()
3136 state()->setDirty(
true);
3137 emit settingsUpdated(getAllSettings());
3139 const int id = OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText());
3140 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3141 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
3142 Options::setCaptureTrainID(
id);
3145void Camera::syncSettings()
3161 value = dsb->
value();
3167 value = sb->
value();
3185 settings().remove(key);
3204 settings()[key] = value;
3205 m_GlobalSettings[key] = value;
3207 Options::self()->setProperty(key.
toLatin1(), value);
3208 m_DebounceTimer.
start();
3212void Camera::connectSyncSettings()
3232 if (oneWidget->isCheckable())
3242 if (oneWidget->objectName() ==
"qt_spinbox_lineedit" || oneWidget->isReadOnly())
3251void Camera::disconnectSyncSettings()
3271 if (oneWidget->isCheckable())
3281 if (oneWidget->objectName() ==
"qt_spinbox_lineedit")
3289 if (!m_settings.contains(key) || m_settings[key].toStringList() != list)
3291 m_settings[key] =
list;
3292 m_DebounceTimer.
start();
3296void Camera::storeTrainKeyString(
const QString &key,
const QString &str)
3298 if (!m_settings.contains(key) || m_settings[key].toString() != str)
3300 m_settings[key] = str;
3301 m_DebounceTimer.
start();
3305void Camera::setupFilterManager()
3308 if (filterManager())
3309 filterManager()->disconnect(
this);
3312 Manager::Instance()->createFilterManager(devices()->filterWheel());
3315 Manager::Instance()->getFilterManager(devices()->filterWheel()->getDeviceName(), m_FilterManager);
3317 devices()->setFilterManager(filterManager());
3319 connect(filterManager().
get(), &FilterManager::updated,
this, [
this]()
3321 emit filterManagerUpdated(devices()->filterWheel());
3325 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::newFilterStatus);
3329 filterManager()->refreshFilterModel();
3330 filterManager()->show();
3331 filterManager()->raise();
3334 connect(filterManager().
get(), &FilterManager::failed,
this, [
this]()
3338 appendLogText(
i18n(
"Filter operation failed."));
3344 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::setFilterStatus);
3346 connect(filterManager().
get(), &FilterManager::labelsChanged,
this, [
this]()
3348 FilterPosCombo->clear();
3349 FilterPosCombo->addItems(filterManager()->getFilterLabels());
3350 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3351 updateCurrentFilterPosition();
3352 storeTrainKey(KEY_FILTERS, filterManager()->getFilterLabels());
3355 connect(filterManager().
get(), &FilterManager::positionChanged,
this, [
this]()
3357 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3358 updateCurrentFilterPosition();
3362void Camera::clearFilterManager()
3365 if (filterManager())
3366 filterManager()->disconnect(
this);
3369 filterManager().
clear();
3370 devices()->setFilterManager(filterManager());
3373void Camera::refreshFilterSettings()
3375 FilterPosCombo->clear();
3377 if (!devices()->filterWheel())
3379 FilterPosLabel->setEnabled(
false);
3380 FilterPosCombo->setEnabled(
false);
3381 filterEditB->setEnabled(
false);
3382 filterManagerB->setEnabled(
false);
3384 clearFilterManager();
3388 FilterPosLabel->setEnabled(
true);
3389 FilterPosCombo->setEnabled(
true);
3390 filterEditB->setEnabled(
true);
3391 filterManagerB->setEnabled(
true);
3393 setupFilterManager();
3395 process()->updateFilterInfo();
3397 const auto labels = process()->filterLabels();
3398 FilterPosCombo->addItems(labels);
3401 storeTrainKey(KEY_FILTERS, labels);
3403 updateCurrentFilterPosition();
3405 filterEditB->setEnabled(state()->getCurrentFilterPosition() > 0);
3406 filterManagerB->setEnabled(state()->getCurrentFilterPosition() > 0);
3408 FilterPosCombo->setCurrentIndex(state()->getCurrentFilterPosition() - 1);
3411void Camera::updateCurrentFilterPosition()
3413 const QString currentFilterText = FilterPosCombo->itemText(m_FilterManager->getFilterPosition() - 1);
3414 state()->setCurrentFilterPosition(m_FilterManager->getFilterPosition(),
3416 m_FilterManager->getFilterLock(currentFilterText));
3420void Camera::setFilterWheel(
QString name)
3426 if (devices()->filterWheel() && devices()->filterWheel()->getDeviceName() == name)
3428 refreshFilterSettings();
3432 auto isConnected = devices()->filterWheel() && devices()->filterWheel()->isConnected();
3433 FilterPosLabel->setEnabled(isConnected);
3434 FilterPosCombo->setEnabled(isConnected);
3435 filterManagerB->setEnabled(isConnected);
3437 refreshFilterSettings();
3439 if (devices()->filterWheel())
3440 emit settingsUpdated(getAllSettings());
3445 return m_DeviceAdaptor->getActiveCamera();
3450 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3451 if (activeCamera() && trainID.
isValid())
3453 auto id = trainID.
toUInt();
3454 auto name = OpticalTrainManager::Instance()->name(
id);
3455 return OpticalTrainManager::Instance()->getScope(name);
3461double Camera::currentReducer()
3463 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3464 if (activeCamera() && trainID.
isValid())
3466 auto id = trainID.
toUInt();
3467 auto name = OpticalTrainManager::Instance()->name(
id);
3468 return OpticalTrainManager::Instance()->getReducer(name);
3474double Camera::currentAperture()
3476 auto scope = currentScope();
3478 double focalLength = scope[
"focal_length"].toDouble(-1);
3479 double aperture = scope[
"aperture"].toDouble(-1);
3480 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3483 if (aperture < 0 && focalRatio > 0)
3484 aperture = focalLength * focalRatio;
3489void Camera::updateMeridianFlipStage(MeridianFlipState::MFStage stage)
3492 if (state()->getMeridianFlipState()->getMeridianFlipStage() != stage)
3496 case MeridianFlipState::MF_READY:
3504 case MeridianFlipState::MF_INITIATED:
3505 captureStatusWidget->setStatus(
i18n(
"Meridian Flip..."),
Qt::yellow);
3506 KSNotification::event(
QLatin1String(
"MeridianFlipStarted"),
i18n(
"Meridian flip started"), KSNotification::Capture);
3509 case MeridianFlipState::MF_COMPLETED:
3510 captureStatusWidget->setStatus(
i18n(
"Flip complete."),
Qt::yellow);
3519void Camera::openExposureCalculatorDialog()
3521 QCINFO <<
"Instantiating an Exposure Calculator";
3524 double preferredSkyQuality = 20.5;
3526 auto scope = currentScope();
3527 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3529 auto reducedFocalLength = currentReducer() * scope[
"focal_length"].toDouble(-1);
3530 auto aperture = currentAperture();
3531 auto reducedFocalRatio = (focalRatio > 0 || aperture == 0) ? focalRatio : reducedFocalLength / aperture;
3533 if (devices()->getActiveCamera() !=
nullptr)
3535 QCINFO <<
"set ExposureCalculator preferred camera to active camera id: "
3536 << devices()->getActiveCamera()->getDeviceName();
3540 preferredSkyQuality,
3542 devices()->getActiveCamera()->getDeviceName()));
3544 anExposureCalculatorDialog->show();
3547void Camera::handleScriptsManager()
3553 m_scriptsManager->setScripts(old_scripts);
3556void Camera::showTemperatureRegulation()
3558 if (!devices()->getActiveCamera())
3561 double currentRamp, currentThreshold;
3562 if (!devices()->getActiveCamera()->getTemperatureRegulation(currentRamp, currentThreshold))
3565 double rMin, rMax, rStep, tMin, tMax, tStep;
3567 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_SLOPE", &rMin, &rMax, &rStep);
3568 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_THRESHOLD", &tMin, &tMax, &tStep);
3570 QLabel rampLabel(
i18nc(
"Maximum temperature variation over time when regulating.",
"Ramp (°C/min):"));
3577 "<p>Maximum temperature change per minute when cooling or warming the camera. Set zero to disable."
3578 "<p>This setting is read from and stored in the INDI camera driver configuration."
3581 QLabel thresholdLabel(
i18nc(
"Temperature threshold above which regulation triggers.",
"Threshold (°C):"));
3586 thresholdSpin.
setValue(currentThreshold);
3588 "<p>Maximum difference between camera and target temperatures triggering regulation."
3589 "<p>This setting is read from and stored in the INDI camera driver configuration."
3593 layout.addRow(&rampLabel, &rampSpin);
3594 layout.addRow(&thresholdLabel, &thresholdSpin);
3600 dialog->setWindowTitle(
i18nc(
"@title:window",
"Set Temperature Regulation"));
3602 dialog->setLayout(&
layout);
3603 dialog->setMinimumWidth(300);
3607 if (devices()->getActiveCamera())
3608 devices()->getActiveCamera()->setTemperatureRegulation(rampSpin.
value(), thresholdSpin.
value());
3612void Camera::createDSLRDialog()
3614 m_DSLRInfoDialog.reset(
new DSLRInfo(
this, devices()->getActiveCamera()));
3616 connect(m_DSLRInfoDialog.get(), &DSLRInfo::infoChanged,
this, [
this]()
3618 if (devices()->getActiveCamera())
3619 addDSLRInfo(QString(devices()->getActiveCamera()->getDeviceName()),
3620 m_DSLRInfoDialog->sensorMaxWidth,
3621 m_DSLRInfoDialog->sensorMaxHeight,
3622 m_DSLRInfoDialog->sensorPixelW,
3623 m_DSLRInfoDialog->sensorPixelH);
3626 m_DSLRInfoDialog->show();
3628 emit dslrInfoRequested(devices()->getActiveCamera()->getDeviceName());
3631void Camera::showObserverDialog()
3636 for (
auto &o : m_observerList)
3637 observers <<
QString(
"%1 %2").
arg(o->name(), o->surname());
3639 QDialog observersDialog(
this);
3640 observersDialog.setWindowTitle(
i18nc(
"@title:window",
"Select Current Observer"));
3644 QComboBox observerCombo(&observersDialog);
3645 observerCombo.addItems(observers);
3646 observerCombo.setCurrentText(getObserverName());
3650 manageObserver.setFixedSize(
QSize(32, 32));
3653 manageObserver.setToolTip(
i18n(
"Manage Observers"));
3662 for (
auto &o : m_observerList)
3663 observers <<
QString(
"%1 %2").
arg(o->name(), o->surname());
3665 observerCombo.
clear();
3666 observerCombo.addItems(observers);
3667 observerCombo.setCurrentText(getObserverName());
3676 observersDialog.setLayout(
layout);
3678 observersDialog.exec();
3679 setObserverName(observerCombo.currentText());
3682void Camera::onStandAloneShow(
QShowEvent *event)
3684 OpticalTrainSettings::Instance()->setOpticalTrainID(Options::captureTrainID());
3685 auto oneSetting = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
3686 setSettings(oneSetting.toJsonObject().toVariantMap());
3691 captureGainN->setValue(GainSpinSpecialValue);
3692 captureOffsetN->setValue(OffsetSpinSpecialValue);
3694 m_standAloneUseCcdGain =
true;
3695 m_standAloneUseCcdOffset =
true;
3696 if (m_settings.contains(KEY_GAIN_KWD) && m_settings[KEY_GAIN_KWD].toString() ==
"CCD_CONTROLS")
3697 m_standAloneUseCcdGain =
false;
3698 if (m_settings.contains(KEY_OFFSET_KWD) && m_settings[KEY_OFFSET_KWD].toString() ==
"CCD_CONTROLS")
3699 m_standAloneUseCcdOffset =
false;
3705 if (captureGainN->value() != GainSpinSpecialValue)
3706 setGain(captureGainN->value());
3714 if (captureOffsetN->value() != OffsetSpinSpecialValue)
3715 setOffset(captureOffsetN->value());
3721void Camera::setStandAloneGain(
double value)
3725 if (m_standAloneUseCcdGain)
3730 ccdGain[
"GAIN"] = value;
3731 propertyMap[
"CCD_GAIN"] = ccdGain;
3735 propertyMap[
"CCD_GAIN"].
remove(
"GAIN");
3736 if (propertyMap[
"CCD_GAIN"].
size() == 0)
3737 propertyMap.
remove(
"CCD_GAIN");
3745 ccdGain[
"Gain"] = value;
3746 propertyMap[
"CCD_CONTROLS"] = ccdGain;
3750 propertyMap[
"CCD_CONTROLS"].
remove(
"Gain");
3751 if (propertyMap[
"CCD_CONTROLS"].
size() == 0)
3752 propertyMap.
remove(
"CCD_CONTROLS");
3756 m_customPropertiesDialog->setCustomProperties(propertyMap);
3759void Camera::setStandAloneOffset(
double value)
3763 if (m_standAloneUseCcdOffset)
3768 ccdOffset[
"OFFSET"] = value;
3769 propertyMap[
"CCD_OFFSET"] = ccdOffset;
3773 propertyMap[
"CCD_OFFSET"].
remove(
"OFFSET");
3774 if (propertyMap[
"CCD_OFFSET"].
size() == 0)
3775 propertyMap.
remove(
"CCD_OFFSET");
3783 ccdOffset[
"Offset"] = value;
3784 propertyMap[
"CCD_CONTROLS"] = ccdOffset;
3788 propertyMap[
"CCD_CONTROLS"].
remove(
"Offset");
3789 if (propertyMap[
"CCD_CONTROLS"].
size() == 0)
3790 propertyMap.
remove(
"CCD_CONTROLS");
3794 m_customPropertiesDialog->setCustomProperties(propertyMap);
3797void Camera::setVideoStreamEnabled(
bool enabled)
3801 liveVideoB->setChecked(
true);
3806 liveVideoB->setChecked(
false);
3812void Camera::setCoolerToggled(
bool enabled)
3814 auto isToggled = (!
enabled && coolerOnB->isChecked()) || (
enabled && coolerOffB->isChecked());
3816 coolerOnB->blockSignals(
true);
3817 coolerOnB->setChecked(
enabled);
3818 coolerOnB->blockSignals(
false);
3820 coolerOffB->blockSignals(
true);
3821 coolerOffB->setChecked(!
enabled);
3822 coolerOffB->blockSignals(
false);
3825 appendLogText(
enabled ?
i18n(
"Cooler is on") :
i18n(
"Cooler is off"));
3828void Camera::setFilterStatus(FilterState filterState)
3830 if (filterState != state()->getFilterManagerState())
3831 QCDEBUG <<
"Filter state changed from" << Ekos::getFilterStatusString(
3832 state()->getFilterManagerState()) <<
"to" << Ekos::getFilterStatusString(filterState);
3835 switch (filterState)
3838 appendLogText(
i18n(
"Changing focus offset by %1 steps...",
3839 filterManager()->getTargetFilterOffset()));
3843 appendLogText(
i18n(
"Changing filter to %1...",
3844 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3847 case FILTER_AUTOFOCUS:
3848 appendLogText(
i18n(
"Auto focus on filter change..."));
3849 clearAutoFocusHFR();
3853 if (state()->getFilterManagerState() == FILTER_CHANGE)
3855 appendLogText(
i18n(
"Filter set to %1.",
3856 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3864 state()->setFilterManagerState(filterState);
3866 captureStatusWidget->setFilterState(filterState);
3869void Camera::resetJobs()
3875 if (m_JobUnderEdit ==
true)
3877 SequenceJob * job = state()->allJobs().at(queueTable->currentRow());
3881 updateJobTable(job);
3887 nullptr,
i18n(
"Are you sure you want to reset status of all jobs?"),
i18n(
"Reset job status"),
3896 updateJobTable(job);
3901 state()->clearCapturedFramesMap();
3904 state()->setIgnoreJobProgress(Options::alwaysResetSequenceWhenStarting());
3907 startB->setEnabled(
true);
3912 if (i.
row() < 0 || (i.
row() + 1) > state()->allJobs().
size())
3917 if (job ==
nullptr || job->jobType() == SequenceJob::JOBTYPE_DARKFLAT)
3922 if (state()->isBusy())
3925 if (state()->allJobs().
size() >= 2)
3927 queueUpB->setEnabled(i.
row() > 0);
3928 queueDownB->setEnabled(i.
row() + 1 < state()->allJobs().
size());
3937 if (selectJob(i) ==
false)
3940 appendLogText(
i18n(
"Editing job #%1...", i.
row() + 1));
3943 addToQueueB->setToolTip(
i18n(
"Apply job changes."));
3944 removeFromQueueB->setToolTip(
i18n(
"Cancel job changes."));
3947 previewB->setDefault(
false);
3948 addToQueueB->setDefault(
true);
3950 m_JobUnderEdit =
true;
3954void Camera::resetJobEdit(
bool cancelled)
3956 if (cancelled ==
true)
3957 appendLogText(
i18n(
"Editing job canceled."));
3959 m_JobUnderEdit =
false;
3962 addToQueueB->setToolTip(
i18n(
"Add job to sequence queue"));
3963 removeFromQueueB->setToolTip(
i18n(
"Remove job from sequence queue"));
3965 addToQueueB->setDefault(
false);
3966 previewB->setDefault(
true);
void processCaptureTimeout()
processCaptureTimeout If exposure timed out, let's handle it.
Q_SCRIPTABLE void resetFrame()
resetFrame Reset frame settings of the camera
Q_SCRIPTABLE void executeJob()
executeJob Start the execution of activeJob by initiating updatePreCaptureCalibrationStatus().
void captureStarted(CaptureResult rc)
captureStarted Manage the result when capturing has been started
void processCaptureError(ISD::Camera::ErrorType type)
processCaptureError Handle when image capture fails
void captureImage()
captureImage Initiates image capture in the active job.
CameraChip class controls a particular chip in camera.
Camera class controls an INDI Camera device.
Rotator class handles control of INDI Rotator devices.
bool GetAllObservers(QList< OAL::Observer * > &observer_list)
Updates the passed reference of observer_list with all observers The original content of the list is ...
const KStarsDateTime & lt() const
static KStars * Instance()
KStarsData * data() const
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.
void setAlt(dms alt)
Sets Alt, the Altitude.
void setAz(dms az)
Sets Az, the Azimuth.
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...)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
@ CAPTURE_SETTING_ROTATOR
@ CAPTURE_CHANGING_FILTER
@ CAPTURE_SETTING_TEMPERATURE
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
QString name(GameStandardAction id)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
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)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QAction * up(const QObject *recvr, const char *slot, QObject *parent)
const QList< QKeySequence > & begin()
QString label(StandardShortcut id)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void doubleClicked(const QModelIndex &index)
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
void activated(int index)
void currentIndexChanged(int index)
void setCurrentText(const QString &text)
void currentTextChanged(const QString &text)
QString toString(QStringView format, QCalendar cal) const const
QString toNativeSeparators(const QString &pathName)
void setMaximum(double max)
void setMinimum(double min)
void setSingleStep(double val)
void setValue(double val)
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)
bool isChecked() const const
QIcon fromTheme(const QString &name)
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
void removeAt(qsizetype i)
void replace(qsizetype i, const QJsonValue &value)
iterator insert(QLatin1StringView key, const QJsonValue &value)
void setText(const QString &)
void textChanged(const QString &text)
void textEdited(const QString &text)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
bool isEmpty() const const
void prepend(parameter_type value)
void removeAt(qsizetype i)
bool removeOne(const AT &t)
size_type remove(const Key &key)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
T findChild(const QString &name, Qt::FindChildOptions options) const const
QList< T > findChildren(Qt::FindChildOptions options) const const
T qobject_cast(QObject *object)
QObject * sender() const const
bool isNull() const const
bool restoreState(const QByteArray &state)
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
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) 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)
void setInterval(int msec)
void setSingleShot(bool singleShot)
QUrl fromLocalFile(const QString &localFile)
bool isEmpty() const const
bool isValid() const const
QString toLocalFile() const const
QString url(FormattingOptions options) const const
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