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);
116 m_DebounceTimer.setInterval(500);
117 m_DebounceTimer.setSingleShot(
true);
120 videoDurationUnitCB->addItem(
i18n(
"sec"));
121 videoDurationUnitCB->addItem(
i18n(
"frames"));
124 targetDriftLabel->setVisible(
false);
125 targetDrift->setVisible(
false);
126 targetDriftUnit->setVisible(
false);
127 avgDownloadTime->setVisible(
false);
128 avgDownloadLabel->setVisible(
false);
129 secLabel->setVisible(
false);
130 darkB->setChecked(Options::autoDark());
170 addToQueueB->setToolTip(
i18n(
"Add job to sequence queue"));
171 removeFromQueueB->setToolTip(
i18n(
"Remove job from sequence queue"));
173 if (Options::remoteCaptureDirectory().isEmpty() ==
false)
175 fileRemoteDirT->setText(Options::remoteCaptureDirectory());
178 if(!Options::captureDirectory().isEmpty())
179 fileDirectoryT->setText(Options::captureDirectory());
188 for (
auto &button : qButtons)
189 button->setAutoDefault(
false);
193 refreshOpticalTrain();
198 foreach (
auto job, state()->allJobs())
201 state()->allJobs().clear();
204void Camera::initCamera()
206 KStarsData::Instance()->
userdb()->GetAllDSLRInfos(state()->DSLRInfos());
207 state()->getSequenceQueue()->loadOptions();
209 if (state()->DSLRInfos().count() > 0)
211 QCDEBUG <<
"DSLR Cameras Info:";
212 QCDEBUG << state()->DSLRInfos();
215 setupOpticalTrainManager();
218 state()->getMeridianFlipState();
235 restartCamera(activeCamera()->getDeviceName());
240 static_cast<void(Camera::*)()
>(&Camera::saveSequenceQueue));
243 &Camera::selectedJobChanged);
247 resetJobEdit(m_JobUnderEdit);
276 state()->updateHFRThreshold();
277 generatePreviewFilename();
288 m_CalibrationUI->captureCalibrationParkMount->setChecked(false);
293 m_CalibrationUI->captureCalibrationWall->setChecked(false);
303 if (devices()->getActiveCamera())
305 QVariantMap auxInfo = devices()->getActiveCamera()->getDriverInfo()->getAuxInfo();
306 auxInfo[QString(
"%1_TC").arg(devices()->getActiveCamera()->getDeviceName())] = toggled;
307 devices()->getActiveCamera()->getDriverInfo()->setAuxInfo(auxInfo);
312 if (devices()->getActiveCamera())
313 devices()->getActiveCamera()->setTemperature(cameraTemperatureN->value());
317 if (devices()->getActiveCamera())
318 devices()->getActiveCamera()->setCoolerControl(
true);
322 if (devices()->getActiveCamera())
323 devices()->getActiveCamera()->setCoolerControl(
false);
329 placeholderFormatT->setText(KSUtils::getDefaultPath(
"PlaceholderFormat"));
333 &Camera::checkFrameType);
337 &Camera::updateVideoDurationUnit);
342 if (checked == false)
343 state()->getRefocusState()->setInSequenceFocus(false);
349 connect(m_cameraState.get(), &CameraState::newLimitFocusHFR,
this, [
this](
double hfr)
351 m_LimitsUI->hFRDeviation->setValue(hfr);
354 state()->getCaptureDelayTimer().setSingleShot(
true);
358 state()->getCaptureTimeout().setSingleShot(
true);
364 &Camera::checkUploadMode);
368 customPropertiesDialog()->show();
369 customPropertiesDialog()->raise();
372 connect(customPropertiesDialog(), &CustomProperties::valueChanged,
this, [&]()
374 const double newGain = getGain();
375 if (captureGainN && newGain >= 0)
376 captureGainN->setValue(newGain);
377 const int newOffset = getOffset();
379 captureOffsetN->setValue(newOffset);
383 connect(m_cameraState.data(), &CameraState::newStatus, captureStatusWidget, &LedStatusWidget::setCaptureState);
388 loadGlobalSettings();
389 connectSyncSettings();
393 updateHFRCheckAlgo();
396 updateHFRCheckAlgo();
399 updateHFRCheckAlgo();
406 generatePreviewFilename();
411 generatePreviewFilename();
415 &Camera::generatePreviewFilename);
418 generatePreviewFilename();
419 QCDEBUG <<
"Changed target to" << targetNameT->text() <<
"because of user edit";
422 placeholderFormatT->setText(Options::placeholderFormat());
425 generatePreviewFilename();
429 connect(m_cameraState.data(), &CameraState::captureBusy,
this, &Camera::setBusy);
430 connect(m_cameraState.data(), &CameraState::startCapture,
this, &Camera::start);
431 connect(m_cameraState.data(), &CameraState::abortCapture,
this, &Camera::abort);
432 connect(m_cameraState.data(), &CameraState::suspendCapture,
this, &Camera::suspend);
433 connect(m_cameraState.data(), &CameraState::newLog,
this, &Camera::appendLogText);
434 connect(m_cameraState.data(), &CameraState::sequenceChanged,
this, &Camera::sequenceChanged);
435 connect(m_cameraState.data(), &CameraState::updatePrepareState,
this, &Camera::updatePrepareState);
436 connect(m_cameraState.data(), &CameraState::newFocusStatus,
this, &Camera::updateFocusStatus);
437 connect(m_cameraState.data(), &CameraState::runAutoFocus,
this,
438 [&](AutofocusReason autofocusReason,
const QString & reasonInfo)
440 emit runAutoFocus(autofocusReason, reasonInfo, opticalTrain());
442 connect(m_cameraState.data(), &CameraState::resetFocusFrame,
this, [&]()
444 emit resetFocusFrame(opticalTrain());
446 connect(m_cameraState.data(), &CameraState::adaptiveFocus,
this, [&]()
448 emit adaptiveFocus(opticalTrain());
450 connect(m_cameraProcess.data(), &CameraProcess::abortFocus,
this, [&]()
452 emit abortFocus(opticalTrain());
454 connect(m_cameraState.data(), &CameraState::newMeridianFlipStage,
this, &Camera::updateMeridianFlipStage);
455 connect(m_cameraState.data(), &CameraState::guideAfterMeridianFlip,
this, &Camera::guideAfterMeridianFlip);
456 connect(m_cameraState.data(), &CameraState::resetNonGuidedDither,
this, [&]()
460 emit resetNonGuidedDither();
462 connect(m_cameraState.data(), &CameraState::newStatus,
this, &Camera::updateCameraStatus);
463 connect(m_cameraState.data(), &CameraState::meridianFlipStarted,
this, [&]()
465 emit meridianFlipStarted(opticalTrain());
468 connect(m_cameraProcess.data(), &CameraProcess::refreshCamera,
this, &Camera::updateCamera);
469 connect(m_cameraProcess.data(), &CameraProcess::sequenceChanged,
this, &Camera::sequenceChanged);
470 connect(m_cameraProcess.data(), &CameraProcess::addJob,
this, &Camera::addJob);
471 connect(m_cameraProcess.data(), &CameraProcess::newExposureProgress,
this, [&](SequenceJob * job)
473 emit newExposureProgress(job, opticalTrain());
475 connect(m_cameraProcess.data(), &CameraProcess::newDownloadProgress,
this, [&](
double downloadTimeLeft)
477 emit updateDownloadProgress(downloadTimeLeft, opticalTrain());
479 connect(m_cameraProcess.data(), &CameraProcess::newImage,
this, [&](SequenceJob * job,
const QSharedPointer<FITSData> data)
481 emit newImage(job, data, opticalTrain());
483 connect(m_cameraProcess.data(), &CameraProcess::captureComplete,
this, [&](
const QVariantMap & metadata)
485 emit captureComplete(metadata, opticalTrain());
487 connect(m_cameraProcess.data(), &CameraProcess::updateCaptureCountDown,
this, &Camera::updateCaptureCountDown);
488 connect(m_cameraProcess.data(), &CameraProcess::processingFITSfinished,
this, &Camera::processingFITSfinished);
489 connect(m_cameraProcess.data(), &CameraProcess::captureStopped,
this, &Camera::captureStopped);
490 connect(m_cameraProcess.data(), &CameraProcess::darkFrameCompleted,
this, &Camera::imageCapturingCompleted);
491 connect(m_cameraProcess.data(), &CameraProcess::updateMeridianFlipStage,
this, &Camera::updateMeridianFlipStage);
492 connect(m_cameraProcess.data(), &CameraProcess::syncGUIToJob,
this, &Camera::syncGUIToJob);
493 connect(m_cameraProcess.data(), &CameraProcess::refreshCameraSettings,
this, &Camera::refreshCameraSettings);
494 connect(m_cameraProcess.data(), &CameraProcess::updateFrameProperties,
this, &Camera::updateFrameProperties);
495 connect(m_cameraProcess.data(), &CameraProcess::rotatorReverseToggled,
this, &Camera::setRotatorReversed);
496 connect(m_cameraProcess.data(), &CameraProcess::refreshFilterSettings,
this, &Camera::refreshFilterSettings);
497 connect(m_cameraProcess.data(), &CameraProcess::suspendGuiding,
this, &Camera::suspendGuiding);
498 connect(m_cameraProcess.data(), &CameraProcess::resumeGuiding,
this, &Camera::resumeGuiding);
499 connect(m_cameraProcess.data(), &CameraProcess::driverTimedout,
this, &Camera::driverTimedout);
500 connect(m_cameraProcess.data(), &CameraProcess::createJob, [
this](SequenceJob::SequenceJobType jobType)
503 process()->jobCreated(createJob(jobType));
505 connect(m_cameraProcess.data(), &CameraProcess::updateJobTable,
this, &Camera::updateJobTable);
506 connect(m_cameraProcess.data(), &CameraProcess::newLog,
this, &Camera::appendLogText);
507 connect(m_cameraProcess.data(), &CameraProcess::stopCapture,
this, &Camera::stop);
508 connect(m_cameraProcess.data(), &CameraProcess::jobStarting,
this, &Camera::jobStarting);
509 connect(m_cameraProcess.data(), &CameraProcess::cameraReady,
this, &Camera::ready);
510 connect(m_cameraProcess.data(), &CameraProcess::captureAborted,
this, &Camera::captureAborted);
511 connect(m_cameraProcess.data(), &CameraProcess::captureRunning,
this, &Camera::captureRunning);
512 connect(m_cameraProcess.data(), &CameraProcess::captureImageStarted,
this, &Camera::captureImageStarted);
513 connect(m_cameraProcess.data(), &CameraProcess::jobExecutionPreparationStarted,
this,
514 &Camera::jobExecutionPreparationStarted);
515 connect(m_cameraProcess.data(), &CameraProcess::jobPrepared,
this, &Camera::jobPrepared);
516 connect(m_cameraProcess.data(), &CameraProcess::captureTarget,
this, &Camera::setTargetName);
517 connect(m_cameraProcess.data(), &CameraProcess::downloadingFrame,
this, [
this]()
519 captureStatusWidget->setStatus(i18n(
"Downloading..."), Qt::yellow);
521 connect(m_cameraProcess.data(), &CameraProcess::requestAction,
this, [&](CaptureWorkflowActionType action)
523 emit requestAction(m_cameraId, action);
527 connect(m_cameraState.data(), &CameraState::executeActiveJob, m_cameraProcess.data(),
529 connect(m_cameraState.data(), &CameraState::captureStarted, m_cameraProcess.data(),
531 connect(m_cameraState.data(), &CameraState::requestAction,
this, [&](CaptureWorkflowActionType action)
533 emit requestAction(m_cameraId, action);
535 connect(m_cameraState.data(), &CameraState::checkFocus,
this, [&](
double hfr)
537 emit checkFocus(hfr, opticalTrain());
539 connect(m_cameraState.data(), &CameraState::resetNonGuidedDither,
this, [&]()
542 emit resetNonGuidedDither();
546 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newCCDTemperatureValue,
this,
548 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::CameraConnected,
this, [
this](
bool connected)
550 CaptureSettingsGroup->setEnabled(connected);
551 fileSettingsGroup->setEnabled(connected);
552 sequenceBox->setEnabled(connected);
553 for (auto &oneChild : sequenceControlsButtonGroup->buttons())
554 oneChild->setEnabled(connected);
557 trainLayout->setEnabled(true);
559 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::FilterWheelConnected,
this, [
this](
bool connected)
561 FilterPosLabel->setEnabled(connected);
562 FilterPosCombo->setEnabled(connected);
563 filterManagerB->setEnabled(connected);
565 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newRotator,
this, &Camera::setRotator);
566 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newRotatorAngle,
this, &Camera::updateRotatorAngle,
568 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::newFilterWheel,
this, &Camera::setFilterWheel);
571 connect(m_cameraState.data(), &CameraState::newFilterPosition,
572 m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::setFilterPosition);
573 connect(m_cameraState.data(), &CameraState::abortFastExposure,
574 m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::abortFastExposure);
577 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::scopeStatusChanged,
578 m_cameraState.data(), &CameraState::setScopeState);
579 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::pierSideChanged,
580 m_cameraState.data(), &CameraState::setPierSide);
581 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::scopeParkStatusChanged,
582 m_cameraState.data(), &CameraState::setScopeParkState);
583 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::domeStatusChanged,
584 m_cameraState.data(), &CameraState::setDomeState);
585 connect(m_DeviceAdaptor.data(), &CaptureDeviceAdaptor::dustCapStatusChanged,
586 m_cameraState.data(), &CameraState::dustCapStateChanged);
589void Camera::updateRotatorAngle(
double value)
591 IPState RState = devices()->rotator()->absoluteAngleState();
592 if (RState == IPS_OK)
593 m_RotatorControlPanel->updateRotator(value);
595 m_RotatorControlPanel->updateGauge(value);
598void Camera::setRotatorReversed(
bool toggled)
600 m_RotatorControlPanel->reverseDirection->setEnabled(
true);
601 m_RotatorControlPanel->reverseDirection->blockSignals(
true);
602 m_RotatorControlPanel->reverseDirection->setChecked(toggled);
603 m_RotatorControlPanel->reverseDirection->blockSignals(
false);
606void Camera::updateCCDTemperature(
double value)
608 if (cameraTemperatureS->isEnabled() ==
false && devices()->getActiveCamera())
610 if (devices()->getActiveCamera()->getPermission(
"CCD_TEMPERATURE") != IP_RO)
611 process()->checkCamera();
614 temperatureOUT->setText(QString(
"%L1º").arg(value, 0,
'f', 1));
616 if (cameraTemperatureN->cleanText().isEmpty())
617 cameraTemperatureN->setValue(value);
620void Camera::setFocusStatus(FocusState newstate)
623 state()->updateFocusState(newstate);
626void Camera::updateFocusStatus(FocusState newstate)
628 if ((state()->getRefocusState()->isRefocusing()
629 || state()->getRefocusState()->isInSequenceFocus()) && activeJob()
630 && activeJob()->getStatus() == JOB_BUSY)
635 appendLogText(
i18n(
"Focus complete."));
636 captureStatusWidget->setStatus(
i18n(
"Focus complete."),
Qt::yellow);
640 captureStatusWidget->setStatus(
i18n(
"Autofocus failed."),
Qt::darkRed);
649void Camera::updateCamera(
bool isValid)
651 auto isConnected = activeCamera() && activeCamera()->isConnected();
652 CaptureSettingsGroup->setEnabled(isConnected);
653 fileSettingsGroup->setEnabled(isConnected);
654 sequenceBox->setEnabled(isConnected);
655 for (
auto &oneChild : sequenceControlsButtonGroup->buttons())
656 oneChild->setEnabled(isConnected);
660 auto name = activeCamera()->getDeviceName();
661 opticalTrainCombo->setToolTip(QString(
"%1 @ %2").arg(name, currentScope()[
"name"].
toString()));
662 emit settingsUpdated(getAllSettings());
663 emit refreshCamera(m_cameraId,
true);
666 emit refreshCamera(m_cameraId,
false);
670void Camera::refreshCameraSettings()
674 auto camera = activeCamera();
675 auto targetChip = devices()->getActiveChip();
677 if (!m_standAlone && (!camera || !targetChip || !targetChip->getCCD() || targetChip->isCapturing()))
683 if (camera->hasCoolerControl())
685 coolerOnB->setEnabled(
true);
686 coolerOffB->setEnabled(
true);
687 coolerOnB->setChecked(camera->isCoolerOn());
688 coolerOffB->setChecked(!camera->isCoolerOn());
692 coolerOnB->setEnabled(
false);
693 coolerOnB->setChecked(
false);
694 coolerOffB->setEnabled(
false);
695 coolerOffB->setChecked(
false);
698 updateFrameProperties();
700 updateCaptureFormats();
702 customPropertiesDialog()->setCCD(camera);
704 liveVideoB->setEnabled(camera->hasVideoStream());
705 if (camera->hasVideoStream())
706 setVideoStreamEnabled(camera->isStreamingEnabled());
722 DarkLibrary::Instance()->checkCamera();
725void Camera::processCameraNumber(INDI::Property prop)
727 if (devices()->getActiveCamera() ==
nullptr)
730 if ((prop.isNameMatch(
"CCD_FRAME") && state()->useGuideHead() ==
false) ||
731 (prop.isNameMatch(
"GUIDER_FRAME") && state()->useGuideHead()))
732 updateFrameProperties();
733 else if ((prop.isNameMatch(
"CCD_INFO") && state()->useGuideHead() ==
false) ||
734 (prop.isNameMatch(
"GUIDER_INFO") && state()->useGuideHead()))
735 updateFrameProperties(1);
736 else if (prop.isNameMatch(
"CCD_TRANSFER_FORMAT") || prop.isNameMatch(
"CCD_CAPTURE_FORMAT"))
737 updateCaptureFormats();
738 else if (prop.isNameMatch(
"CCD_CONTROLS"))
740 auto nvp = prop.getNumber();
741 auto gain = nvp->findWidgetByName(
"Gain");
744 auto offset = nvp->findWidgetByName(
"Offset");
748 else if (prop.isNameMatch(
"CCD_GAIN"))
750 auto nvp = prop.getNumber();
751 currentGainLabel->setText(
QString::number(nvp->at(0)->getValue(),
'f', 0));
753 else if (prop.isNameMatch(
"CCD_OFFSET"))
755 auto nvp = prop.getNumber();
756 currentOffsetLabel->setText(
QString::number(nvp->at(0)->getValue(),
'f', 0));
761void Camera::updateTargetDistance(
double targetDiff)
764 targetDriftLabel->setVisible(
true);
765 targetDrift->setVisible(
true);
766 targetDriftUnit->setVisible(
true);
768 targetDrift->setText(QString(
"%L1").arg(targetDiff, 0,
'd', 1));
773QString frameLabel(CCDFrameType type,
const QString &filter)
780 return CCDFrameTypeNames[
type];
786 return CCDFrameTypeNames[
type];
788 return QString(
"%1 %2").arg(filter).arg(CCDFrameTypeNames[type]);
794 return CCDFrameTypeNames[
type];
799void Camera::captureRunning()
801 emit captureStarting(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(),
802 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString());
803 if (isActiveJobPreview())
804 frameInfoLabel->setText(
"Expose (-/-):");
805 else if (activeJob()->getFrameType() != FRAME_VIDEO)
806 frameInfoLabel->setText(QString(
"%1 (%L2/%L3):").arg(frameLabel(activeJob()->getFrameType(),
807 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()))
808 .arg(activeJob()->getCompleted()).arg(activeJob()->getCoreProperty(
809 SequenceJob::SJ_Count).toInt()));
811 frameInfoLabel->setText(QString(
"%1 (%2x%L3s):").arg(frameLabel(activeJob()->getFrameType(),
812 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()))
813 .arg(activeJob()->getCoreProperty(SequenceJob::SJ_Count).toInt())
814 .arg(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f', 3));
817 avgDownloadTime->setVisible(
true);
818 avgDownloadLabel->setVisible(
true);
819 secLabel->setVisible(
true);
821 avgDownloadTime->setText(QString(
"%L1").arg(state()->averageDownloadTime(), 0,
'd', 2));
824 if (state()->isLooping() ==
false)
826 if (activeJob()->getFrameType() == FRAME_VIDEO)
827 appendLogText(
i18n(
"Capturing %1 x %2-second %3 video...",
828 activeJob()->getCoreProperty(SequenceJob::SJ_Count).toInt(),
829 QString(
"%L1").arg(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f', 3),
830 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()));
832 else if (activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
833 appendLogText(
i18n(
"Capturing %1-second %2 image...",
834 QString(
"%L1").arg(activeJob()->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f', 3),
835 activeJob()->getCoreProperty(SequenceJob::SJ_Filter).
toString()));
839void Camera::captureImageStarted()
841 if (devices()->filterWheel() !=
nullptr)
843 updateCurrentFilterPosition();
847 if (activeJob()->getCalibrationStage() == SequenceJobState::CAL_CALIBRATION)
848 captureStatusWidget->setStatus(
i18n(
"Calibrating..."),
Qt::yellow);
851void Camera::jobExecutionPreparationStarted()
853 if (activeJob() ==
nullptr)
856 qWarning(KSTARS_EKOS_CAPTURE) <<
"jobExecutionPreparationStarted with null state()->getActiveJob().";
859 if (activeJob()->jobType() == SequenceJob::JOBTYPE_PREVIEW)
860 updateStartButtons(
true,
false);
863void Camera::jobPrepared(SequenceJob * job)
865 int index = state()->allJobs().indexOf(job);
867 queueTable->selectRow(index);
869 if (activeJob()->jobType() != SequenceJob::JOBTYPE_PREVIEW)
872 imgProgress->setEnabled(
true);
873 imgProgress->setMaximum(activeJob()->getCoreProperty(SequenceJob::SJ_Count).toInt());
874 imgProgress->setValue(activeJob()->getCompleted());
878void Camera::setTargetName(
const QString &newTargetName)
881 if (activeJob() ==
nullptr)
884 targetNameT->setText(newTargetName);
885 auto rows = queueTable->selectionModel()->selectedRows();
889 int pos = rows.constFirst().row();
891 if (state()->allJobs().
size() >
pos)
892 state()->allJobs().at(
pos)->setCoreProperty(SequenceJob::SJ_TargetName, newTargetName);
895 emit captureTarget(newTargetName);
899void Camera::jobStarting()
901 if (m_LimitsUI->enforceAutofocusHFR->isChecked() && state()->getRefocusState()->isAutoFocusReady() ==
false)
902 appendLogText(
i18n(
"Warning: in-sequence focusing is selected but autofocus process was not started."));
903 if (m_LimitsUI->enforceAutofocusOnTemperature->isChecked()
904 && state()->getRefocusState()->isAutoFocusReady() ==
false)
905 appendLogText(
i18n(
"Warning: temperature delta check is selected but autofocus process was not started."));
907 updateStartButtons(
true,
false);
911void Camera::capturePreview()
913 process()->capturePreview();
916void Camera::startFraming()
918 process()->capturePreview(
true);
921void Camera::generateDarkFlats()
923 const auto existingJobs = state()->allJobs().size();
924 uint8_t jobsAdded = 0;
926 for (
int i = 0; i < existingJobs; i++)
928 if (state()->allJobs().at(i)->getFrameType() != FRAME_FLAT)
931 syncGUIToJob(state()->allJobs().at(i));
933 captureTypeS->setCurrentIndex(FRAME_DARK);
934 createJob(SequenceJob::JOBTYPE_DARKFLAT);
940 appendLogText(
i18np(
"One dark flats job was created.",
"%1 dark flats jobs were created.", jobsAdded));
944void Camera::updateDownloadProgress(
double downloadTimeLeft,
const QString &devicename)
946 frameRemainingTime->setText(state()->imageCountDown().
toString(
"hh:mm:ss"));
947 emit newDownloadProgress(downloadTimeLeft, devicename);
950void Camera::updateCaptureCountDown(
int deltaMillis)
952 state()->imageCountDownAddMSecs(deltaMillis);
953 state()->sequenceCountDownAddMSecs(deltaMillis);
954 frameRemainingTime->setText(state()->imageCountDown().
toString(
"hh:mm:ss"));
955 if (!isActiveJobPreview())
956 jobRemainingTime->setText(state()->sequenceCountDown().
toString(
"hh:mm:ss"));
958 jobRemainingTime->setText(
"--:--:--");
961void Camera::addJob(SequenceJob * job)
964 createNewJobTableRow(job);
967void Camera::editJobFinished()
969 if (queueTable->currentRow() < 0)
970 QCWARNING <<
"Editing finished, but no row selected!";
972 int currentRow = queueTable->currentRow();
973 SequenceJob *job = state()->allJobs().at(currentRow);
974 updateJobFromUI(job);
977 updateJobTable(job,
true);
980 QJsonObject jsonJob = createJsonJob(job, currentRow);
981 state()->getSequence().replace(currentRow, jsonJob);
982 emit sequenceChanged(state()->getSequence());
985 appendLogText(
i18n(
"Job #%1 changes applied.", currentRow + 1));
988void Camera::imageCapturingCompleted()
990 SequenceJob *thejob = activeJob();
996 if (state()->isLooping())
1004 if (devices()->getActiveCamera()->isFastExposureEnabled() ==
false)
1005 DarkLibrary::Instance()->disconnect(
this);
1008 if (thejob->getCoreProperty(SequenceJob::SJ_Exposure).toDouble() >= 1)
1009 KSNotification::event(QLatin1String(
"EkosCaptureImageReceived"),
i18n(
"Captured image received"),
1010 KSNotification::Capture);
1013 if (thejob->jobType() == SequenceJob::JOBTYPE_PREVIEW)
1017 imgProgress->setValue(thejob->getCompleted());
1020void Camera::captureStopped()
1022 imgProgress->reset();
1023 imgProgress->setEnabled(
false);
1025 frameRemainingTime->setText(
"--:--:--");
1026 jobRemainingTime->setText(
"--:--:--");
1027 frameInfoLabel->setText(
i18n(
"Expose (-/-):"));
1030 auto captureState = state()->getCaptureState();
1032 updateStartButtons(
false,
false);
1035void Camera::processingFITSfinished(
bool success)
1038 if (success ==
false)
1042 if (devices()->getActiveCamera()
1043 && devices()->getActiveCamera()->getUploadMode() != ISD::Camera::UPLOAD_REMOTE)
1044 previewB->setEnabled(
true);
1046 imageCapturingCompleted();
1049void Camera::checkFrameType(
int index)
1051 updateCaptureFormats();
1053 calibrationB->setEnabled(index != FRAME_LIGHT);
1054 generateDarkFlatsB->setEnabled(index != FRAME_LIGHT);
1055 const bool isVideo = captureTypeS->currentText() == CAPTURE_TYPE_VIDEO;
1056 exposureOptions->setCurrentIndex(isVideo ? 1 : 0);
1057 exposureOptionsLabel->setToolTip(isVideo ?
i18n(
"Duration of the video sequence") :
i18n(
"Number of images to capture"));
1058 exposureOptionsLabel->setText(isVideo ?
i18n(
"Duration:") :
i18n(
"Count:"));
1059 exposureLabel->setToolTip(isVideo ?
i18n(
"Exposure time in seconds of a single video frame") :
1060 i18n(
"Exposure time in seconds for individual images"));
1064 selectUploadMode(ISD::Camera::UPLOAD_REMOTE);
1066 checkUploadMode(fileUploadModeS->currentIndex());
1069void Camera::updateStartButtons(
bool start,
bool pause)
1075 startB->setToolTip(
i18n(
"Stop Sequence"));
1081 startB->setToolTip(
i18n(pause ?
"Resume Sequence" :
"Start Sequence"));
1083 pauseB->setEnabled(start && !pause);
1086void Camera::setBusy(
bool enable)
1088 previewB->setEnabled(!enable);
1089 loopB->setEnabled(!enable);
1090 opticalTrainCombo->setEnabled(!enable);
1091 trainB->setEnabled(!enable);
1093 foreach (QAbstractButton * button, queueEditButtonGroup->buttons())
1098void Camera::updatePrepareState(
CaptureState prepareState)
1100 state()->setCaptureState(prepareState);
1102 if (activeJob() ==
nullptr)
1104 qWarning(KSTARS_EKOS_CAPTURE) <<
"updatePrepareState with null activeJob().";
1109 switch (prepareState)
1112 appendLogText(
i18n(
"Setting temperature to %1 °C...", activeJob()->getTargetTemperature()));
1113 captureStatusWidget->setStatus(
i18n(
"Set Temp to %1 °C...", activeJob()->getTargetTemperature()),
1117 appendLogText(
i18n(
"Waiting for guide drift below %1\"...", Options::startGuideDeviation()));
1118 captureStatusWidget->setStatus(
i18n(
"Wait for Guider < %1\"...", Options::startGuideDeviation()),
Qt::yellow);
1122 appendLogText(
i18n(
"Setting camera to %1 degrees E of N...", activeJob()->getTargetRotation()));
1123 captureStatusWidget->setStatus(
i18n(
"Set Camera to %1 deg...", activeJob()->getTargetRotation()),
1133SequenceJob *Camera::createJob(SequenceJob::SequenceJobType jobtype, FilenamePreviewType filenamePreview)
1135 SequenceJob *job =
new SequenceJob(devices(), state(), jobtype);
1137 updateJobFromUI(job, filenamePreview);
1140 if (jobtype == SequenceJob::JOBTYPE_PREVIEW || filenamePreview != FILENAME_NOT_PREVIEW)
1144 if (checkUploadPaths(filenamePreview, job) ==
false)
1148 state()->allJobs().append(job);
1151 createNewJobTableRow(job);
1156bool Camera::removeJob(
int index)
1168 if (index < 0 || index >= state()->allJobs().count())
1171 queueTable->removeRow(index);
1172 QJsonArray seqArray = state()->getSequence();
1174 state()->setSequence(seqArray);
1175 emit sequenceChanged(seqArray);
1177 if (state()->allJobs().empty())
1180 SequenceJob * job = state()->allJobs().at(index);
1182 state()->removeCapturedFrameCount(job->getSignature(), job->getCompleted());
1184 state()->allJobs().removeOne(job);
1185 if (job == activeJob())
1186 state()->setActiveJob(
nullptr);
1190 if (queueTable->rowCount() == 0)
1191 removeFromQueueB->setEnabled(
false);
1193 if (queueTable->rowCount() == 1)
1195 queueUpB->setEnabled(
false);
1196 queueDownB->setEnabled(
false);
1199 if (index < queueTable->rowCount())
1200 queueTable->selectRow(index);
1201 else if (queueTable->rowCount() > 0)
1202 queueTable->selectRow(queueTable->rowCount() - 1);
1204 if (queueTable->rowCount() == 0)
1206 queueSaveAsB->setEnabled(
false);
1207 queueSaveB->setEnabled(
false);
1208 resetB->setEnabled(
false);
1211 state()->setDirty(
true);
1216bool Camera::modifyJob(
int index)
1224 if (index < 0 || index >= state()->allJobs().count())
1227 queueTable->selectRow(index);
1228 auto modelIndex = queueTable->model()->index(index, 0);
1229 editJob(modelIndex);
1233void Camera::loadSequenceQueue()
1237 "Ekos Sequence Queue (*.esq)");
1241 if (fileURL.
isValid() ==
false)
1244 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1253void Camera::saveSequenceQueue()
1255 QUrl backupCurrent = state()->sequenceURL();
1257 if (state()->sequenceURL().toLocalFile().startsWith(QLatin1String(
"/tmp/"))
1258 || state()->sequenceURL().toLocalFile().contains(
"/Temp"))
1259 state()->setSequenceURL(QUrl(
""));
1262 if (state()->dirty() ==
false && !state()->sequenceURL().isEmpty())
1265 if (state()->sequenceURL().isEmpty())
1268 "Save Ekos Sequence Queue"),
1270 "Ekos Sequence Queue (*.esq)"));
1272 if (state()->sequenceURL().isEmpty())
1274 state()->setSequenceURL(backupCurrent);
1280 if (state()->sequenceURL().toLocalFile().endsWith(QLatin1String(
".esq")) ==
false)
1281 state()->setSequenceURL(QUrl(
"file:" + state()->sequenceURL().toLocalFile() +
".esq"));
1285 if (state()->sequenceURL().
isValid())
1288 if ((process()->saveSequenceQueue(state()->sequenceURL().toLocalFile(), !m_standAlone)) ==
false)
1290 KSNotification::error(
i18n(
"Failed to save sequence queue"),
i18n(
"Save"));
1294 state()->setDirty(
false);
1298 QString message =
i18n(
"Invalid URL: %1", state()->sequenceURL().url());
1299 KSNotification::sorry(message,
i18n(
"Invalid URL"));
1304void Camera::saveSequenceQueueAs()
1306 state()->setSequenceURL(QUrl(
""));
1307 saveSequenceQueue();
1310void Camera::updateJobTable(SequenceJob * job,
bool full)
1314 QListIterator<SequenceJob *> iter(state()->allJobs());
1315 while (iter.hasNext())
1316 updateJobTable(iter.next(), full);
1321 int row = state()->allJobs().indexOf(job);
1322 if (row >= 0 && row < queueTable->rowCount())
1324 updateRowStyle(job);
1325 QTableWidgetItem *
status = queueTable->item(row, JOBTABLE_COL_STATUS);
1326 QTableWidgetItem *count = queueTable->item(row, JOBTABLE_COL_COUNTS);
1327 status->setText(job->getStatusString());
1328 updateJobTableCountCell(job, count);
1332 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
1334 QTableWidgetItem *
filter = queueTable->item(row, JOBTABLE_COL_FILTER);
1335 if (FilterPosCombo->findText(job->getCoreProperty(SequenceJob::SJ_Filter).toString()) >= 0 &&
1336 (captureTypeS->currentIndex() == FRAME_LIGHT || captureTypeS->currentIndex() == FRAME_FLAT
1337 || captureTypeS->currentIndex() == FRAME_VIDEO || isDarkFlat) )
1338 filter->setText(job->getCoreProperty(SequenceJob::SJ_Filter).toString());
1342 QTableWidgetItem *exp = queueTable->item(row, JOBTABLE_COL_EXP);
1343 exp->
setText(QString(
"%L1").arg(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble(), 0,
'f',
1344 captureExposureN->decimals()));
1346 QTableWidgetItem *
type = queueTable->item(row, JOBTABLE_COL_TYPE);
1347 type->setText(isDarkFlat ?
i18n(
"Dark Flat") : CCDFrameTypeNames[job->getFrameType()]);
1349 QTableWidgetItem *
bin = queueTable->item(row, JOBTABLE_COL_BINNING);
1350 QPoint binning = job->getCoreProperty(SequenceJob::SJ_Binning).toPoint();
1351 bin->setText(QString(
"%1x%2").arg(binning.
x()).arg(binning.
y()));
1353 QTableWidgetItem *iso = queueTable->item(row, JOBTABLE_COL_ISO);
1354 if (job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt() != -1)
1355 iso->
setText(captureISOS->itemText(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt()));
1356 else if (job->getCoreProperty(SequenceJob::SJ_Gain).toDouble() >= 0)
1361 QTableWidgetItem *offset = queueTable->item(row, JOBTABLE_COL_OFFSET);
1362 if (job->getCoreProperty(SequenceJob::SJ_Offset).toDouble() >= 0)
1369 queueTable->resizeColumnsToContents();
1373 if (queueTable->rowCount() > 0)
1375 queueSaveAsB->setEnabled(
true);
1376 queueSaveB->setEnabled(
true);
1377 resetB->setEnabled(
true);
1378 state()->setDirty(
true);
1381 if (queueTable->rowCount() > 1)
1383 queueUpB->setEnabled(
true);
1384 queueDownB->setEnabled(
true);
1390void Camera::updateJobFromUI(SequenceJob * job, FilenamePreviewType filenamePreview)
1392 job->setCoreProperty(SequenceJob::SJ_Format, captureFormatS->currentText());
1393 job->setCoreProperty(SequenceJob::SJ_Encoding, captureEncodingS->currentText());
1396 job->setISO(captureISOS->currentIndex());
1398 job->setCoreProperty(SequenceJob::SJ_Gain, getGain());
1399 job->setCoreProperty(SequenceJob::SJ_Offset, getOffset());
1401 if (cameraTemperatureN->isEnabled())
1403 job->setCoreProperty(SequenceJob::SJ_EnforceTemperature, cameraTemperatureS->isChecked());
1404 job->setTargetTemperature(cameraTemperatureN->value());
1407 job->setScripts(m_scriptsManager->getScripts());
1408 job->setUploadMode(
static_cast<ISD::Camera::UploadMode
>(fileUploadModeS->currentIndex()));
1411 job->setFlatFieldDuration(m_CalibrationUI->captureCalibrationDurationManual->isChecked() ? DURATION_MANUAL :
1414 int action = CAPTURE_PREACTION_NONE;
1415 if (m_CalibrationUI->captureCalibrationParkMount->isChecked())
1416 action |= CAPTURE_PREACTION_PARK_MOUNT;
1417 if (m_CalibrationUI->captureCalibrationParkDome->isChecked())
1418 action |= CAPTURE_PREACTION_PARK_DOME;
1419 if (m_CalibrationUI->captureCalibrationWall->isChecked())
1421 bool azOk =
false, altOk =
false;
1422 auto wallAz = m_CalibrationUI->azBox->createDms(&azOk);
1423 auto wallAlt = m_CalibrationUI->altBox->createDms(&altOk);
1427 action = (action & ~CAPTURE_PREACTION_PARK_MOUNT) | CAPTURE_PREACTION_WALL;
1428 SkyPoint wallSkyPoint;
1429 wallSkyPoint.
setAz(wallAz);
1430 wallSkyPoint.
setAlt(wallAlt);
1431 job->setWallCoord(wallSkyPoint);
1435 if (m_CalibrationUI->captureCalibrationUseADU->isChecked())
1437 job->setCoreProperty(SequenceJob::SJ_TargetADU, m_CalibrationUI->captureCalibrationADUValue->value());
1438 job->setCoreProperty(SequenceJob::SJ_TargetADUTolerance,
1439 m_CalibrationUI->captureCalibrationADUTolerance->value());
1440 job->setCoreProperty(SequenceJob::SJ_SkyFlat, m_CalibrationUI->captureCalibrationSkyFlats->isChecked());
1443 job->setCalibrationPreAction(action);
1445 job->setFrameType(
static_cast<CCDFrameType
>(qMax(0, captureTypeS->currentIndex())));
1447 if (FilterPosCombo->currentIndex() != -1 && (m_standAlone || devices()->filterWheel() !=
nullptr))
1448 job->setTargetFilter(FilterPosCombo->currentIndex() + 1, FilterPosCombo->currentText());
1450 job->setCoreProperty(SequenceJob::SJ_Exposure, captureExposureN->value());
1452 if (captureTypeS->currentText() == CAPTURE_TYPE_VIDEO)
1454 if (videoDurationUnitCB->currentIndex() == 0)
1456 job->setCoreProperty(SequenceJob::SJ_Count,
static_cast<int>(videoDurationSB->value() / captureExposureN->value()));
1459 job->setCoreProperty(SequenceJob::SJ_Count,
static_cast<int>(videoDurationSB->value()));
1463 job->setCoreProperty(SequenceJob::SJ_Count, captureCountN->value());
1465 job->setCoreProperty(SequenceJob::SJ_Binning, QPoint(captureBinHN->value(), captureBinVN->value()));
1468 job->setCoreProperty(SequenceJob::SJ_Delay, captureDelayN->value() * 1000);
1471 job->setCustomProperties(customPropertiesDialog()->getCustomProperties());
1473 job->setCoreProperty(SequenceJob::SJ_ROI, QRect(captureFrameXN->value(), captureFrameYN->value(),
1474 captureFrameWN->value(),
1475 captureFrameHN->value()));
1476 job->setCoreProperty(SequenceJob::SJ_RemoteDirectory, fileRemoteDirT->text());
1477 job->setCoreProperty(SequenceJob::SJ_LocalDirectory, fileDirectoryT->text());
1478 job->setCoreProperty(SequenceJob::SJ_TargetName, targetNameT->text());
1479 job->setCoreProperty(SequenceJob::SJ_PlaceholderFormat, placeholderFormatT->text());
1480 job->setCoreProperty(SequenceJob::SJ_PlaceholderSuffix, formatSuffixN->value());
1482 job->setCoreProperty(SequenceJob::SJ_DitherPerJobEnabled, m_LimitsUI->enableDitherPerJob->isChecked());
1483 job->setCoreProperty(SequenceJob::SJ_DitherPerJobFrequency, m_LimitsUI->guideDitherPerJobFrequency->value());
1485 auto placeholderPath = PlaceholderPath();
1486 placeholderPath.updateFullPrefix(job, placeholderFormatT->text());
1488 QString signature = placeholderPath.generateSequenceFilename(*job,
1489 filenamePreview != FILENAME_REMOTE_PREVIEW,
true, 1,
1490 ".fits",
"",
false,
true);
1491 job->setCoreProperty(SequenceJob::SJ_Signature, signature);
1495void Camera::selectUploadMode(
int index)
1497 fileUploadModeS->setCurrentIndex(index);
1498 checkUploadMode(index);
1501void Camera::checkUploadMode(
int index)
1503 fileRemoteDirT->setEnabled(index != ISD::Camera::UPLOAD_CLIENT);
1505 const bool isVideo = captureTypeS->currentText() == CAPTURE_TYPE_VIDEO;
1518 generatePreviewFilename();
1521void Camera::syncGUIToJob(SequenceJob * job)
1525 qWarning(KSTARS_EKOS_CAPTURE) <<
"syncGuiToJob with null job.";
1530 const auto roi = job->getCoreProperty(SequenceJob::SJ_ROI).toRect();
1532 captureTypeS->setCurrentIndex(job->getFrameType());
1533 captureFormatS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Format).toString());
1534 captureEncodingS->setCurrentText(job->getCoreProperty(SequenceJob::SJ_Encoding).toString());
1535 captureExposureN->setValue(job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble());
1536 captureBinHN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().x());
1537 captureBinVN->setValue(job->getCoreProperty(SequenceJob::SJ_Binning).toPoint().y());
1538 captureFrameXN->setValue(roi.x());
1539 captureFrameYN->setValue(roi.y());
1540 captureFrameWN->setValue(roi.width());
1541 captureFrameHN->setValue(roi.height());
1542 FilterPosCombo->setCurrentIndex(job->getTargetFilter() - 1);
1543 captureCountN->setValue(job->getCoreProperty(SequenceJob::SJ_Count).toInt());
1544 captureDelayN->setValue(job->getCoreProperty(SequenceJob::SJ_Delay).toInt() / 1000);
1545 targetNameT->setText(job->getCoreProperty(SequenceJob::SJ_TargetName).toString());
1546 fileDirectoryT->setText(job->getCoreProperty(SequenceJob::SJ_LocalDirectory).toString());
1547 selectUploadMode(job->getUploadMode());
1548 fileRemoteDirT->setText(job->getCoreProperty(SequenceJob::SJ_RemoteDirectory).toString());
1549 placeholderFormatT->setText(job->getCoreProperty(SequenceJob::SJ_PlaceholderFormat).toString());
1550 formatSuffixN->setValue(job->getCoreProperty(SequenceJob::SJ_PlaceholderSuffix).toUInt());
1553 cameraTemperatureS->setChecked(job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool());
1554 if (job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toBool())
1555 cameraTemperatureN->setValue(job->getTargetTemperature());
1558 m_LimitsUI->enableDitherPerJob->setChecked(job->getCoreProperty(SequenceJob::SJ_DitherPerJobEnabled).toBool());
1559 if (m_LimitsUI->enableDitherPerJob->isChecked())
1560 m_LimitsUI->guideDitherPerJobFrequency->setValue(job->getCoreProperty(SequenceJob::SJ_DitherPerJobFrequency).toInt());
1562 syncLimitSettings();
1565 calibrationB->setEnabled(job->getFrameType() != FRAME_LIGHT);
1566 generateDarkFlatsB->setEnabled(job->getFrameType() != FRAME_LIGHT);
1568 if (job->getFlatFieldDuration() == DURATION_MANUAL)
1569 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1571 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1574 const auto action = job->getCalibrationPreAction();
1575 if (action & CAPTURE_PREACTION_WALL)
1577 m_CalibrationUI->azBox->setText(job->getWallCoord().az().toDMSString());
1578 m_CalibrationUI->altBox->setText(job->getWallCoord().alt().toDMSString());
1580 m_CalibrationUI->captureCalibrationWall->setChecked(action & CAPTURE_PREACTION_WALL);
1581 m_CalibrationUI->captureCalibrationParkMount->setChecked(action & CAPTURE_PREACTION_PARK_MOUNT);
1582 m_CalibrationUI->captureCalibrationParkDome->setChecked(action & CAPTURE_PREACTION_PARK_DOME);
1585 switch (job->getFlatFieldDuration())
1587 case DURATION_MANUAL:
1588 m_CalibrationUI->captureCalibrationDurationManual->setChecked(
true);
1592 m_CalibrationUI->captureCalibrationUseADU->setChecked(
true);
1593 m_CalibrationUI->captureCalibrationADUValue->setValue(job->getCoreProperty(SequenceJob::SJ_TargetADU).toUInt());
1594 m_CalibrationUI->captureCalibrationADUTolerance->setValue(job->getCoreProperty(
1595 SequenceJob::SJ_TargetADUTolerance).toUInt());
1596 m_CalibrationUI->captureCalibrationSkyFlats->setChecked(job->getCoreProperty(SequenceJob::SJ_SkyFlat).toBool());
1600 m_scriptsManager->setScripts(job->getScripts());
1603 customPropertiesDialog()->setCustomProperties(job->getCustomProperties());
1606 captureISOS->setCurrentIndex(job->getCoreProperty(SequenceJob::SJ_ISOIndex).toInt());
1608 double gain = getGain();
1610 captureGainN->setValue(gain);
1612 captureGainN->setValue(GainSpinSpecialValue);
1614 double offset = getOffset();
1616 captureOffsetN->setValue(offset);
1618 captureOffsetN->setValue(OffsetSpinSpecialValue);
1621 generatePreviewFilename();
1623 if (m_RotatorControlPanel)
1625 if (job->getTargetRotation() != Ekos::INVALID_VALUE)
1628 m_RotatorControlPanel->setCameraPA(job->getTargetRotation());
1636 if (Options::alignCheckFrequency() == 0)
1638 targetDriftLabel->setVisible(
false);
1639 targetDrift->setVisible(
false);
1640 targetDriftUnit->setVisible(
false);
1644void Camera::syncCameraInfo()
1646 if (!activeCamera())
1649 const QString timestamp = KStarsData::Instance()->
lt().
toString(
"yyyy-MM-dd hh:mm");
1650 storeTrainKeyString(KEY_TIMESTAMP, timestamp);
1652 if (activeCamera()->hasCooler())
1654 cameraTemperatureS->setEnabled(
true);
1655 cameraTemperatureN->setEnabled(
true);
1657 if (activeCamera()->getPermission(
"CCD_TEMPERATURE") != IP_RO)
1659 double min, max, step;
1660 setTemperatureB->setEnabled(
true);
1661 cameraTemperatureN->setReadOnly(
false);
1662 cameraTemperatureS->setEnabled(
true);
1663 temperatureRegulationB->setEnabled(
true);
1664 activeCamera()->getMinMaxStep(
"CCD_TEMPERATURE",
"CCD_TEMPERATURE_VALUE", &min, &max, &step);
1665 cameraTemperatureN->setMinimum(min);
1666 cameraTemperatureN->setMaximum(max);
1667 cameraTemperatureN->setSingleStep(1);
1668 bool isChecked = activeCamera()->getDriverInfo()->getAuxInfo().value(QString(
"%1_TC").arg(activeCamera()->getDeviceName()),
1670 cameraTemperatureS->setChecked(isChecked);
1673 const QStringList temperatureList =
1676 isChecked ?
"1" :
"0" } );
1677 storeTrainKey(KEY_TEMPERATURE, temperatureList);
1681 setTemperatureB->setEnabled(
false);
1682 cameraTemperatureN->setReadOnly(
true);
1683 cameraTemperatureS->setEnabled(
false);
1684 cameraTemperatureS->setChecked(
false);
1685 temperatureRegulationB->setEnabled(
false);
1688 const QStringList temperatureList = QStringList( {
"-50",
"50",
"0" } );
1689 storeTrainKey(KEY_TEMPERATURE, temperatureList);
1692 double temperature = 0;
1693 if (activeCamera()->getTemperature(&temperature))
1695 temperatureOUT->setText(QString(
"%L1º").arg(temperature, 0,
'f', 1));
1696 if (cameraTemperatureN->cleanText().isEmpty())
1697 cameraTemperatureN->setValue(temperature);
1702 cameraTemperatureS->setEnabled(
false);
1703 cameraTemperatureN->setEnabled(
false);
1704 temperatureRegulationB->setEnabled(
false);
1705 cameraTemperatureN->clear();
1706 temperatureOUT->clear();
1707 setTemperatureB->setEnabled(
false);
1710 auto isoList = devices()->getActiveChip()->getISOList();
1711 captureISOS->blockSignals(
true);
1712 captureISOS->setEnabled(
false);
1713 captureISOS->clear();
1716 if (isoList.isEmpty())
1718 captureISOS->setEnabled(
false);
1719 if (settings().contains(KEY_ISOS))
1721 settings().remove(KEY_ISOS);
1722 m_DebounceTimer.start();
1724 if (settings().contains(KEY_INDEX))
1726 settings().remove(KEY_INDEX);
1727 m_DebounceTimer.start();
1732 captureISOS->setEnabled(
true);
1733 captureISOS->addItems(isoList);
1734 const int isoIndex = devices()->getActiveChip()->getISOIndex();
1735 captureISOS->setCurrentIndex(isoIndex);
1738 storeTrainKey(KEY_ISOS, isoList);
1739 storeTrainKeyString(KEY_INDEX, QString(
"%1").arg(isoIndex));
1743 double pixelX = 0, pixelY = 0;
1744 bool rc = devices()->getActiveChip()->getImageInfo(w, h, pixelX, pixelY, bbp);
1745 bool isModelInDB = state()->isModelinDSLRInfo(QString(activeCamera()->getDeviceName()));
1748 if (rc ==
true && (pixelX == 0.0 || pixelY == 0.0 || isModelInDB ==
false))
1752 if (isModelInDB ==
false)
1758 QString model = QString(activeCamera()->getDeviceName());
1759 process()->syncDSLRToTargetChip(model);
1763 captureISOS->blockSignals(
false);
1766 if (activeCamera()->hasGain())
1768 double min, max, step, value, targetCustomGain;
1769 activeCamera()->getGainMinMaxStep(&min, &max, &step);
1772 GainSpinSpecialValue = min - step;
1773 captureGainN->setRange(GainSpinSpecialValue, max);
1774 captureGainN->setSpecialValueText(
i18n(
"--"));
1775 captureGainN->setEnabled(
true);
1776 captureGainN->setSingleStep(step);
1777 activeCamera()->getGain(&value);
1780 targetCustomGain = getGain();
1784 if (targetCustomGain > 0)
1785 captureGainN->setValue(targetCustomGain);
1787 captureGainN->setValue(GainSpinSpecialValue);
1789 captureGainN->setReadOnly(activeCamera()->getGainPermission() == IP_RO);
1793 if (captureGainN->value() != GainSpinSpecialValue)
1794 setGain(captureGainN->value());
1801 captureGainN->setEnabled(
false);
1802 currentGainLabel->clear();
1806 if (activeCamera()->hasOffset())
1808 double min, max, step, value, targetCustomOffset;
1809 activeCamera()->getOffsetMinMaxStep(&min, &max, &step);
1812 OffsetSpinSpecialValue = min - step;
1813 captureOffsetN->setRange(OffsetSpinSpecialValue, max);
1814 captureOffsetN->setSpecialValueText(
i18n(
"--"));
1815 captureOffsetN->setEnabled(
true);
1816 captureOffsetN->setSingleStep(step);
1817 activeCamera()->getOffset(&value);
1820 targetCustomOffset = getOffset();
1824 if (targetCustomOffset > 0)
1825 captureOffsetN->setValue(targetCustomOffset);
1827 captureOffsetN->setValue(OffsetSpinSpecialValue);
1829 captureOffsetN->setReadOnly(activeCamera()->getOffsetPermission() == IP_RO);
1833 if (captureOffsetN->value() != OffsetSpinSpecialValue)
1834 setOffset(captureOffsetN->value());
1841 captureOffsetN->setEnabled(
false);
1842 currentOffsetLabel->clear();
1846void Camera::createNewJobTableRow(SequenceJob * job)
1848 int currentRow = queueTable->rowCount();
1849 queueTable->insertRow(currentRow);
1852 QTableWidgetItem *
status =
new QTableWidgetItem();
1856 QTableWidgetItem *
filter =
new QTableWidgetItem();
1860 QTableWidgetItem *count =
new QTableWidgetItem();
1864 QTableWidgetItem *exp =
new QTableWidgetItem();
1868 QTableWidgetItem *
type =
new QTableWidgetItem();
1872 QTableWidgetItem *
bin =
new QTableWidgetItem();
1876 QTableWidgetItem *iso =
new QTableWidgetItem();
1880 QTableWidgetItem *offset =
new QTableWidgetItem();
1885 queueTable->setItem(currentRow, JOBTABLE_COL_STATUS, status);
1886 queueTable->setItem(currentRow, JOBTABLE_COL_FILTER, filter);
1887 queueTable->setItem(currentRow, JOBTABLE_COL_COUNTS, count);
1888 queueTable->setItem(currentRow, JOBTABLE_COL_EXP, exp);
1889 queueTable->setItem(currentRow, JOBTABLE_COL_TYPE, type);
1890 queueTable->setItem(currentRow, JOBTABLE_COL_BINNING, bin);
1891 queueTable->setItem(currentRow, JOBTABLE_COL_ISO, iso);
1892 queueTable->setItem(currentRow, JOBTABLE_COL_OFFSET, offset);
1895 updateJobTable(job,
true);
1898 QJsonObject jsonJob = createJsonJob(job, currentRow);
1899 state()->getSequence().append(jsonJob);
1900 emit sequenceChanged(state()->getSequence());
1902 removeFromQueueB->setEnabled(
true);
1905void Camera::updateRowStyle(SequenceJob * job)
1911 int row = state()->allJobs().indexOf(job);
1912 if (row >= 0 && row < queueTable->rowCount())
1914 updateCellStyle(queueTable->item(row, JOBTABLE_COL_STATUS), job->getStatus() == JOB_BUSY);
1915 updateCellStyle(queueTable->item(row, JOBTABLE_COL_FILTER), job->getStatus() == JOB_BUSY);
1916 updateCellStyle(queueTable->item(row, JOBTABLE_COL_COUNTS), job->getStatus() == JOB_BUSY);
1917 updateCellStyle(queueTable->item(row, JOBTABLE_COL_EXP), job->getStatus() == JOB_BUSY);
1918 updateCellStyle(queueTable->item(row, JOBTABLE_COL_TYPE), job->getStatus() == JOB_BUSY);
1919 updateCellStyle(queueTable->item(row, JOBTABLE_COL_BINNING), job->getStatus() == JOB_BUSY);
1920 updateCellStyle(queueTable->item(row, JOBTABLE_COL_ISO), job->getStatus() == JOB_BUSY);
1921 updateCellStyle(queueTable->item(row, JOBTABLE_COL_OFFSET), job->getStatus() == JOB_BUSY);
1925void Camera::updateCellStyle(QTableWidgetItem * cell,
bool active)
1927 if (cell ==
nullptr)
1931 font.setBold(active);
1932 font.setItalic(active);
1936bool Camera::syncControl(
const QVariantMap &settings,
const QString &key, QWidget * widget)
1938 QSpinBox *pSB =
nullptr;
1939 QDoubleSpinBox *pDSB =
nullptr;
1940 QCheckBox *pCB =
nullptr;
1941 QComboBox *pComboBox =
nullptr;
1942 QSplitter *pSplitter =
nullptr;
1943 QRadioButton *pRadioButton =
nullptr;
1944 QLineEdit *pLineEdit =
nullptr;
1949 const int value = settings[key].toInt(&ok);
1958 const double value = settings[key].toDouble(&ok);
1963 if (pDSB == captureGainN)
1965 if (captureGainN->value() != GainSpinSpecialValue)
1966 setGain(captureGainN->value());
1970 else if (pDSB == captureOffsetN)
1972 if (captureOffsetN->value() != OffsetSpinSpecialValue)
1973 setOffset(captureOffsetN->value());
1982 const bool value = settings[key].toBool();
1989 const bool value = settings[key].toBool();
1997 const QString value = settings[key].toString();
2009 const auto value = settings[key].toString();
2012 if (pLineEdit == fileRemoteDirT)
2013 generatePreviewFilename();
2020void Camera::moveJob(
bool up)
2022 int currentRow = queueTable->currentRow();
2023 int destinationRow =
up ? currentRow - 1 : currentRow + 1;
2025 int columnCount = queueTable->columnCount();
2027 if (currentRow < 0 || destinationRow < 0 || destinationRow >= queueTable->rowCount())
2030 for (
int i = 0; i < columnCount; i++)
2032 QTableWidgetItem * selectedLine = queueTable->takeItem(currentRow, i);
2033 QTableWidgetItem * counterpart = queueTable->takeItem(destinationRow, i);
2035 queueTable->setItem(destinationRow, i, selectedLine);
2036 queueTable->setItem(currentRow, i, counterpart);
2039 SequenceJob * job = state()->allJobs().takeAt(currentRow);
2041 state()->allJobs().removeOne(job);
2042 state()->allJobs().insert(destinationRow, job);
2044 QJsonArray seqArray = state()->getSequence();
2045 QJsonObject currentJob = seqArray[currentRow].toObject();
2046 seqArray.
replace(currentRow, seqArray[destinationRow]);
2047 seqArray.
replace(destinationRow, currentJob);
2048 emit sequenceChanged(seqArray);
2050 queueTable->selectRow(destinationRow);
2052 state()->setDirty(
true);
2055void Camera::removeJobFromQueue()
2057 int currentRow = queueTable->currentRow();
2060 currentRow = queueTable->rowCount() - 1;
2062 removeJob(currentRow);
2065 if (queueTable->rowCount() == 0)
2068 if (currentRow > queueTable->rowCount())
2069 queueTable->selectRow(queueTable->rowCount() - 1);
2071 queueTable->selectRow(currentRow);
2074void Camera::saveFITSDirectory()
2077 m_dirPath.toLocalFile());
2084void Camera::updateCaptureFormats()
2086 if (!activeCamera())
return;
2089 QStringList frameTypes = process()->frameTypes();
2091 QString currentType = captureTypeS->currentText();
2093 captureTypeS->blockSignals(
true);
2094 captureTypeS->clear();
2097 captureTypeS->setEnabled(
false);
2100 captureTypeS->setEnabled(
true);
2101 captureTypeS->addItems(frameTypes);
2103 if (currentType ==
"")
2106 captureTypeS->setCurrentIndex(devices()->getActiveChip()->getFrameType());
2107 currentType = captureTypeS->currentText();
2110 captureTypeS->setCurrentText(currentType);
2112 captureTypeS->blockSignals(
false);
2114 const bool isVideo = currentType == CAPTURE_TYPE_VIDEO;
2117 captureFormatS->blockSignals(
true);
2118 captureFormatS->clear();
2119 const auto list = isVideo ? activeCamera()->getVideoFormats() : activeCamera()->getCaptureFormats();
2120 captureFormatS->addItems(list);
2121 storeTrainKey(KEY_FORMATS, list);
2122 captureFormatS->setCurrentText(activeCamera()->getCaptureFormat());
2123 captureFormatS->blockSignals(
false);
2126 captureEncodingS->blockSignals(
true);
2127 captureEncodingS->clear();
2128 captureEncodingS->addItems(isVideo ? activeCamera()->getStreamEncodings() : activeCamera()->getEncodingFormats());
2129 captureEncodingS->setCurrentText(isVideo ? activeCamera()->getStreamEncoding() : activeCamera()->getEncodingFormat());
2130 captureEncodingS->blockSignals(
false);
2133void Camera::updateHFRCheckAlgo()
2136 const bool threshold = (m_LimitsUI->hFRCheckAlgorithm->currentIndex() != HFR_CHECK_FIXED);
2137 m_LimitsUI->hFRThresholdPercentage->setEnabled(threshold);
2138 m_LimitsUI->limitFocusHFRThresholdLabel->setEnabled(threshold);
2139 m_LimitsUI->limitFocusHFRPercentLabel->setEnabled(threshold);
2140 state()->updateHFRThreshold();
2143void Camera::clearAutoFocusHFR()
2145 if (Options::hFRCheckAlgorithm() == HFR_CHECK_FIXED)
2148 m_LimitsUI->hFRDeviation->setValue(0);
2152void Camera::selectedJobChanged(QModelIndex current, QModelIndex previous)
2158void Camera::clearCameraConfiguration()
2164 devices()->getActiveCamera()->setConfig(PURGE_CONFIG);
2165 KStarsData::Instance()->
userdb()->DeleteDSLRInfo(devices()->getActiveCamera()->getDeviceName());
2167 QStringList shutterfulCCDs = Options::shutterfulCCDs();
2168 QStringList shutterlessCCDs = Options::shutterlessCCDs();
2171 if (shutterfulCCDs.
contains(devices()->getActiveCamera()->getDeviceName()))
2173 shutterfulCCDs.
removeOne(devices()->getActiveCamera()->getDeviceName());
2174 Options::setShutterfulCCDs(shutterfulCCDs);
2176 if (shutterlessCCDs.
contains(devices()->getActiveCamera()->getDeviceName()))
2178 shutterlessCCDs.
removeOne(devices()->getActiveCamera()->getDeviceName());
2179 Options::setShutterlessCCDs(shutterlessCCDs);
2183 if (captureISOS && captureISOS->count() > 0)
2189 KSMessageBox::Instance()->questionYesNo(
i18n(
"Reset %1 configuration to default?",
2190 devices()->getActiveCamera()->getDeviceName()),
2191 i18n(
"Confirmation"), 30);
2194void Camera::editFilterName()
2199 for (
int index = 0; index < FilterPosCombo->count(); index++)
2200 labels << FilterPosCombo->itemText(index);
2201 QStringList newLabels;
2202 if (editFilterNameInternal(labels, newLabels))
2204 FilterPosCombo->clear();
2205 FilterPosCombo->addItems(newLabels);
2210 if (devices()->filterWheel() ==
nullptr || state()->getCurrentFilterPosition() < 1)
2213 QStringList labels = filterManager()->getFilterLabels();
2214 QStringList newLabels;
2215 if (editFilterNameInternal(labels, newLabels))
2216 filterManager()->setFilterNames(newLabels);
2220bool Camera::editFilterNameInternal(
const QStringList &labels, QStringList &newLabels)
2222 QDialog filterDialog;
2224 QFormLayout *formLayout =
new QFormLayout(&filterDialog);
2225 QVector<QLineEdit *> newLabelEdits;
2227 for (uint8_t i = 0; i < labels.
count(); i++)
2229 QLabel *existingLabel =
new QLabel(QString(
"%1. <b>%2</b>").arg(i + 1).arg(labels[i]), &filterDialog);
2230 QLineEdit *newLabel =
new QLineEdit(labels[i], &filterDialog);
2231 newLabelEdits.
append(newLabel);
2232 formLayout->
addRow(existingLabel, newLabel);
2235 QString title = m_standAlone ?
2236 "Edit Filter Names" : devices()->filterWheel()->getDeviceName();
2246 QStringList results;
2247 for (uint8_t i = 0; i < labels.
count(); i++)
2248 results << newLabelEdits[i]->text();
2249 newLabels = results;
2255void Camera::updateVideoDurationUnit()
2257 if (videoDurationUnitCB->currentIndex() == 0)
2260 videoDurationSB->setValue(videoDurationSB->value() * captureExposureN->value());
2261 videoDurationSB->setDecimals(2);
2266 videoDurationSB->setValue(videoDurationSB->value() / captureExposureN->value());
2267 videoDurationSB->setDecimals(0);
2271void Camera::loadGlobalSettings()
2276 QVariantMap settings;
2280 if (oneWidget->objectName() ==
"opticalTrainCombo")
2283 key = oneWidget->objectName();
2284 value = Options::self()->property(key.
toLatin1());
2285 if (value.
isValid() && oneWidget->count() > 0)
2287 oneWidget->setCurrentText(value.
toString());
2288 settings[key] = value;
2291 QCDEBUG <<
"Option" << key <<
"not found!";
2297 key = oneWidget->objectName();
2298 value = Options::self()->property(key.
toLatin1());
2301 oneWidget->setValue(value.
toDouble());
2302 settings[key] = value;
2305 QCDEBUG <<
"Option" << key <<
"not found!";
2311 key = oneWidget->objectName();
2312 value = Options::self()->property(key.
toLatin1());
2315 oneWidget->setValue(value.
toInt());
2316 settings[key] = value;
2319 QCDEBUG <<
"Option" << key <<
"not found!";
2325 key = oneWidget->objectName();
2326 value = Options::self()->property(key.
toLatin1());
2329 oneWidget->setChecked(value.
toBool());
2330 settings[key] = value;
2333 QCDEBUG <<
"Option" << key <<
"not found!";
2339 if (oneWidget->isCheckable())
2341 key = oneWidget->objectName();
2342 value = Options::self()->property(key.
toLatin1());
2345 oneWidget->setChecked(value.
toBool());
2346 settings[key] = value;
2349 QCDEBUG <<
"Option" << key <<
"not found!";
2356 key = oneWidget->objectName();
2357 value = Options::self()->property(key.
toLatin1());
2360 oneWidget->setChecked(value.
toBool());
2361 settings[key] = value;
2368 if (oneWidget->objectName() ==
"qt_spinbox_lineedit" || oneWidget->isReadOnly())
2370 key = oneWidget->objectName();
2371 value = Options::self()->property(key.
toLatin1());
2374 oneWidget->setText(value.
toString());
2375 settings[key] = value;
2378 m_GlobalSettings = settings;
2379 setSettings(settings);
2382bool Camera::checkUploadPaths(FilenamePreviewType filenamePreview, SequenceJob *job)
2385 if (filenamePreview != FILENAME_NOT_PREVIEW)
2388 if (fileUploadModeS->currentIndex() != ISD::Camera::UPLOAD_CLIENT && job->getRemoteDirectory().toString().isEmpty())
2390 KSNotification::error(
i18n(
"You must set local or remote directory for Remotely & Both modes."));
2394 if (fileUploadModeS->currentIndex() != ISD::Camera::UPLOAD_REMOTE && fileDirectoryT->text().isEmpty())
2396 KSNotification::error(
i18n(
"You must set local directory for Locally & Both modes."));
2403QJsonObject Camera::createJsonJob(SequenceJob * job,
int currentRow)
2406 return QJsonObject();
2408 QJsonObject jsonJob = {{
"Status",
"Idle"}};
2409 bool isDarkFlat = job->jobType() == SequenceJob::JOBTYPE_DARKFLAT;
2410 jsonJob.
insert(
"Filter", FilterPosCombo->itemText(job->getTargetFilter() - 1));
2411 jsonJob.
insert(
"Count", queueTable->item(currentRow, JOBTABLE_COL_COUNTS)->text());
2412 jsonJob.
insert(
"Exp", queueTable->item(currentRow, JOBTABLE_COL_EXP)->text());
2413 jsonJob.
insert(
"Type", isDarkFlat ?
i18n(
"Dark Flat") : queueTable->item(currentRow, JOBTABLE_COL_TYPE)->text());
2414 jsonJob.
insert(
"Bin", queueTable->item(currentRow, JOBTABLE_COL_BINNING)->text());
2415 jsonJob.
insert(
"ISO/Gain", queueTable->item(currentRow, JOBTABLE_COL_ISO)->text());
2416 jsonJob.
insert(
"Offset", queueTable->item(currentRow, JOBTABLE_COL_OFFSET)->text());
2417 jsonJob.
insert(
"Encoding", job->getCoreProperty(SequenceJob::SJ_Encoding).toJsonValue());
2418 jsonJob.
insert(
"Format", job->getCoreProperty(SequenceJob::SJ_Format).toJsonValue());
2419 jsonJob.
insert(
"Temperature", job->getTargetTemperature());
2420 jsonJob.
insert(
"EnforceTemperature", job->getCoreProperty(SequenceJob::SJ_EnforceTemperature).toJsonValue());
2421 jsonJob.
insert(
"DitherPerJobEnabled", job->getCoreProperty(SequenceJob::SJ_DitherPerJobEnabled).toJsonValue());
2422 jsonJob.
insert(
"DitherPerJobFrequency", job->getCoreProperty(SequenceJob::SJ_DitherPerJobFrequency).toJsonValue());
2427void Camera::generatePreviewFilename()
2429 if (state()->isCaptureRunning() ==
false)
2431 placeholderFormatT->setToolTip(previewFilename( fileUploadModeS->currentIndex() == ISD::Camera::UPLOAD_REMOTE ?
2432 FILENAME_REMOTE_PREVIEW : FILENAME_LOCAL_PREVIEW ));
2433 emit newLocalPreview(placeholderFormatT->toolTip());
2435 if (fileUploadModeS->currentIndex() != ISD::Camera::UPLOAD_CLIENT)
2436 fileRemoteDirT->setToolTip(previewFilename( FILENAME_REMOTE_PREVIEW ));
2440QString Camera::previewFilename(FilenamePreviewType previewType)
2442 QString previewText;
2446 if (previewType == FILENAME_LOCAL_PREVIEW)
2448 if(!fileDirectoryT->text().endsWith(separator) && !placeholderFormatT->text().startsWith(separator))
2449 placeholderFormatT->setText(separator + placeholderFormatT->text());
2450 m_format = fileDirectoryT->text() + placeholderFormatT->text() + formatSuffixN->prefix() +
2451 formatSuffixN->cleanText();
2453 else if (previewType == FILENAME_REMOTE_PREVIEW)
2454 m_format = fileRemoteDirT->text().
isEmpty() ? fileDirectoryT->text() : fileRemoteDirT->text();
2462 else if (state()->sequenceURL().toLocalFile().isEmpty() && m_format.
contains(
"%f"))
2463 previewText = (
"Save the sequence file to show filename preview");
2467 SequenceJob *m_job = createJob(SequenceJob::JOBTYPE_PREVIEW, previewType);
2468 if (m_job ==
nullptr)
2472 if (state()->sequenceURL().toLocalFile().isEmpty())
2478 previewSeq = state()->sequenceURL().toLocalFile();
2479 auto m_placeholderPath = PlaceholderPath(previewSeq);
2482 if (captureEncodingS->currentText() ==
"FITS")
2483 extension =
".fits";
2484 else if (captureEncodingS->currentText() ==
"XISF")
2485 extension =
".xisf";
2487 extension =
".[NATIVE]";
2488 previewText = m_placeholderPath.generateSequenceFilename(*m_job, previewType == FILENAME_LOCAL_PREVIEW,
true, 1,
2489 extension,
"",
false);
2492 m_job->deleteLater();
2496 if (previewType == FILENAME_REMOTE_PREVIEW)
2497 previewText.
replace(separator,
"/");
2502void Camera::updateJobTableCountCell(SequenceJob * job, QTableWidgetItem * countCell)
2504 countCell->
setText(QString(
"%L1/%L2").arg(job->getCompleted()).arg(job->getCoreProperty(SequenceJob::SJ_Count).toInt()));
2507void Camera::addDSLRInfo(
const QString &model, uint32_t maxW, uint32_t maxH,
double pixelW,
double pixelH)
2510 auto pos = std::find_if(state()->DSLRInfos().
begin(), state()->DSLRInfos().
end(), [model](
const auto & oneDSLRInfo)
2512 return (oneDSLRInfo[
"Model"] == model);
2515 if (
pos != state()->DSLRInfos().
end())
2517 KStarsData::Instance()->
userdb()->DeleteDSLRInfo(model);
2518 state()->DSLRInfos().removeOne(*
pos);
2521 QMap<QString, QVariant> oneDSLRInfo;
2522 oneDSLRInfo[
"Model"] = model;
2523 oneDSLRInfo[
"Width"] = maxW;
2524 oneDSLRInfo[
"Height"] = maxH;
2525 oneDSLRInfo[
"PixelW"] = pixelW;
2526 oneDSLRInfo[
"PixelH"] = pixelH;
2528 KStarsData::Instance()->
userdb()->AddDSLRInfo(oneDSLRInfo);
2529 KStarsData::Instance()->
userdb()->GetAllDSLRInfos(state()->DSLRInfos());
2531 updateFrameProperties();
2532 process()->resetFrame();
2533 process()->syncDSLRToTargetChip(model);
2536 if (m_DSLRInfoDialog)
2537 m_DSLRInfoDialog.reset();
2542 process()->startNextPendingJob();
2547 process()->stopCapturing(targetState);
2552 process()->pauseCapturing();
2553 updateStartButtons(
false,
true);
2556void Camera::toggleSequence()
2558 const CaptureState capturestate = state()->getCaptureState();
2560 updateStartButtons(
true,
false);
2562 process()->toggleSequence();
2565void Camera::toggleVideo(
bool enabled)
2567 process()->toggleVideo(
enabled);
2570void Camera::restartCamera(
const QString &name)
2572 process()->restartCamera(name);
2575void Camera::cullToDSLRLimits()
2577 QString model(devices()->getActiveCamera()->getDeviceName());
2580 auto pos = std::find_if(state()->DSLRInfos().
begin(),
2581 state()->DSLRInfos().
end(), [model](QMap<QString, QVariant> &oneDSLRInfo)
2583 return (oneDSLRInfo[
"Model"] == model);
2586 if (
pos != state()->DSLRInfos().
end())
2588 if (captureFrameWN->maximum() == 0 || captureFrameWN->maximum() > (*
pos)[
"Width"].toInt())
2590 captureFrameWN->setValue((*
pos)[
"Width"].toInt());
2591 captureFrameWN->setMaximum((*
pos)[
"Width"].toInt());
2594 if (captureFrameHN->maximum() == 0 || captureFrameHN->maximum() > (*
pos)[
"Height"].toInt())
2596 captureFrameHN->setValue((*
pos)[
"Height"].toInt());
2597 captureFrameHN->setMaximum((*
pos)[
"Height"].toInt());
2602void Camera::resetFrameToZero()
2604 captureFrameXN->setMinimum(0);
2605 captureFrameXN->setMaximum(0);
2606 captureFrameXN->setValue(0);
2608 captureFrameYN->setMinimum(0);
2609 captureFrameYN->setMaximum(0);
2610 captureFrameYN->setValue(0);
2612 captureFrameWN->setMinimum(0);
2613 captureFrameWN->setMaximum(0);
2614 captureFrameWN->setValue(0);
2616 captureFrameHN->setMinimum(0);
2617 captureFrameHN->setMaximum(0);
2618 captureFrameHN->setValue(0);
2621void Camera::updateFrameProperties(
int reset)
2623 if (!devices()->getActiveCamera())
2626 int binx = 1, biny = 1;
2627 double min, max, step;
2628 int xstep = 0, ystep = 0;
2630 QString frameProp = state()->useGuideHead() ? QString(
"GUIDER_FRAME") : QString(
"CCD_FRAME");
2631 QString exposureProp = state()->useGuideHead() ? QString(
"GUIDER_EXPOSURE") : QString(
"CCD_EXPOSURE");
2632 QString exposureElem = state()->useGuideHead() ? QString(
"GUIDER_EXPOSURE_VALUE") :
2633 QString(
"CCD_EXPOSURE_VALUE");
2634 devices()->setActiveChip(state()->useGuideHead() ?
2635 devices()->getActiveCamera()->getChip(
2636 ISD::CameraChip::GUIDE_CCD) :
2637 devices()->getActiveCamera()->getChip(ISD::CameraChip::PRIMARY_CCD));
2639 captureFrameWN->setEnabled(devices()->getActiveChip()->canSubframe());
2640 captureFrameHN->setEnabled(devices()->getActiveChip()->canSubframe());
2641 captureFrameXN->setEnabled(devices()->getActiveChip()->canSubframe());
2642 captureFrameYN->setEnabled(devices()->getActiveChip()->canSubframe());
2644 captureBinHN->setEnabled(devices()->getActiveChip()->canBin());
2645 captureBinVN->setEnabled(devices()->getActiveChip()->canBin());
2647 QList<double> exposureValues;
2648 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 <<
2649 10 << 20 << 30 << 40 << 50 << 60 << 120 << 180 << 300 << 600 << 900 << 1200 << 1800;
2651 if (devices()->getActiveCamera()->getMinMaxStep(exposureProp, exposureElem, &min, &max, &step))
2654 captureExposureN->setDecimals(6);
2656 captureExposureN->setDecimals(3);
2657 for(
int i = 0; i < exposureValues.
count(); i++)
2659 double value = exposureValues.
at(i);
2660 if(value < min || value > max)
2668 exposureValues.
append(max);
2671 captureExposureN->setRecommendedValues(exposureValues);
2672 state()->setExposureRange(exposureValues.
first(), exposureValues.
last());
2674 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"WIDTH", &min, &max, &step))
2683 xstep =
static_cast<int>(max * 0.05);
2685 xstep =
static_cast<int>(step);
2687 if (min >= 0 && max > 0)
2689 captureFrameWN->setMinimum(
static_cast<int>(min));
2690 captureFrameWN->setMaximum(
static_cast<int>(max));
2691 captureFrameWN->setSingleStep(xstep);
2697 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"HEIGHT", &min, &max, &step))
2706 ystep =
static_cast<int>(max * 0.05);
2708 ystep =
static_cast<int>(step);
2710 if (min >= 0 && max > 0)
2712 captureFrameHN->setMinimum(
static_cast<int>(min));
2713 captureFrameHN->setMaximum(
static_cast<int>(max));
2714 captureFrameHN->setSingleStep(ystep);
2720 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"X", &min, &max, &step))
2731 if (min >= 0 && max > 0)
2733 captureFrameXN->setMinimum(
static_cast<int>(min));
2734 captureFrameXN->setMaximum(
static_cast<int>(max));
2735 captureFrameXN->setSingleStep(
static_cast<int>(step));
2741 if (devices()->getActiveCamera()->getMinMaxStep(frameProp,
"Y", &min, &max, &step))
2752 if (min >= 0 && max > 0)
2754 captureFrameYN->setMinimum(
static_cast<int>(min));
2755 captureFrameYN->setMaximum(
static_cast<int>(max));
2756 captureFrameYN->setSingleStep(
static_cast<int>(step));
2763 if (state()->useGuideHead() ==
false)
2766 const QString ccdGainKeyword = devices()->getActiveCamera()->getProperty(
"CCD_GAIN") ?
"CCD_GAIN" :
"CCD_CONTROLS";
2767 storeTrainKeyString(KEY_GAIN_KWD, ccdGainKeyword);
2769 const QString ccdOffsetKeyword = devices()->getActiveCamera()->getProperty(
"CCD_OFFSET") ?
"CCD_OFFSET" :
"CCD_CONTROLS";
2770 storeTrainKeyString(KEY_OFFSET_KWD, ccdOffsetKeyword);
2772 if (reset == 1 || state()->frameSettings().contains(devices()->getActiveChip()) ==
false)
2774 QVariantMap settings;
2778 settings[
"w"] = captureFrameWN->maximum();
2779 settings[
"h"] = captureFrameHN->maximum();
2780 settings[
"binx"] = captureBinHN->value();
2781 settings[
"biny"] = captureBinVN->value();
2783 state()->frameSettings()[devices()->getActiveChip()] = settings;
2785 else if (reset == 2 && state()->frameSettings().contains(devices()->getActiveChip()))
2787 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2790 x = settings[
"x"].toInt();
2791 y = settings[
"y"].toInt();
2792 w = settings[
"w"].toInt();
2793 h = settings[
"h"].toInt();
2796 x = qBound(captureFrameXN->minimum(),
x, captureFrameXN->maximum() - 1);
2797 y = qBound(captureFrameYN->minimum(),
y, captureFrameYN->maximum() - 1);
2798 w = qBound(captureFrameWN->minimum(), w, captureFrameWN->maximum());
2799 h = qBound(captureFrameHN->minimum(), h, captureFrameHN->maximum());
2805 settings[
"binx"] = captureBinHN->value();
2806 settings[
"biny"] = captureBinVN->value();
2808 state()->frameSettings()[devices()->getActiveChip()] = settings;
2811 if (state()->frameSettings().contains(devices()->getActiveChip()))
2813 QVariantMap settings = state()->frameSettings()[devices()->getActiveChip()];
2814 int x = settings[
"x"].toInt();
2815 int y = settings[
"y"].toInt();
2816 int w = settings[
"w"].toInt();
2817 int h = settings[
"h"].toInt();
2819 if (devices()->getActiveChip()->canBin())
2821 devices()->getActiveChip()->getMaxBin(&binx, &biny);
2822 captureBinHN->setMaximum(binx);
2823 captureBinVN->setMaximum(biny);
2825 captureBinHN->setValue(settings[
"binx"].toInt());
2826 captureBinVN->setValue(settings[
"biny"].toInt());
2830 captureBinHN->setValue(1);
2831 captureBinVN->setValue(1);
2835 captureFrameXN->setValue(
x);
2837 captureFrameYN->setValue(
y);
2839 captureFrameWN->setValue(w);
2841 captureFrameHN->setValue(h);
2847void Camera::setGain(
double value)
2851 setStandAloneGain(value);
2854 if (!devices()->getActiveCamera())
2857 QMap<QString, QMap<QString, QVariant> > customProps = customPropertiesDialog()->getCustomProperties();
2858 process()->updateGain(value, customProps);
2859 customPropertiesDialog()->setCustomProperties(customProps);
2863double Camera::getGain()
2865 return devices()->cameraGain(customPropertiesDialog()->getCustomProperties());
2868void Camera::setOffset(
double value)
2872 setStandAloneOffset(value);
2875 if (!devices()->getActiveCamera())
2878 QMap<QString, QMap<QString, QVariant> > customProps = customPropertiesDialog()->getCustomProperties();
2880 process()->updateOffset(value, customProps);
2881 customPropertiesDialog()->setCustomProperties(customProps);
2884double Camera::getOffset()
2886 return devices()->cameraOffset(customPropertiesDialog()->getCustomProperties());
2889void Camera::setRotator(QString name)
2891 ISD::Rotator *Rotator = devices()->rotator();
2893 rotatorB->setEnabled(
false);
2894 if (Rotator && !m_RotatorControlPanel.isNull())
2895 m_RotatorControlPanel->close();
2900 Manager::Instance()->getRotatorController(name, m_RotatorControlPanel);
2901 m_RotatorControlPanel->initRotator(opticalTrainCombo->currentText(), devices().data(),
2905 m_RotatorControlPanel->show();
2906 m_RotatorControlPanel->raise();
2908 rotatorB->setEnabled(
true);
2910 else if (Options::astrometryUseRotator())
2912 RotatorUtils::Instance()->initRotatorUtils(opticalTrainCombo->currentText());
2916void Camera::setMaximumGuidingDeviation(
bool enable,
double value)
2918 m_LimitsUI->enforceGuideDeviation->setChecked(enable);
2920 m_LimitsUI->guideDeviation->setValue(value);
2923void Camera::setInSequenceFocus(
bool enable,
double HFR)
2925 m_LimitsUI->enforceAutofocusHFR->setChecked(enable);
2927 m_LimitsUI->hFRDeviation->setValue(HFR);
2930bool Camera::loadSequenceQueue(
const QString &fileURL, QString targetName)
2932 QFile sFile(fileURL);
2935 QString message =
i18n(
"Unable to open file %1", fileURL);
2936 KSNotification::sorry(message,
i18n(
"Could Not Open File"));
2940 state()->clearCapturedFramesMap();
2941 clearSequenceQueue();
2944 const bool result = process()->loadSequenceQueue(fileURL, targetName, !m_standAlone);
2946 if (result ==
false)
2950 setObserverName(state()->observerName());
2953 if (state()->allJobs().
size() > 0)
2954 syncGUIToJob(state()->allJobs().first());
2957 queueSaveB->setToolTip(
"Save to " + sFile.fileName());
2962bool Camera::saveSequenceQueue(
const QString &path)
2965 return process()->saveSequenceQueue(path);
2971 emit newStatus(status, opticalTrain(), cameraId());
2974void Camera::clearSequenceQueue()
2976 state()->setActiveJob(
nullptr);
2977 while (queueTable->rowCount() > 0)
2978 queueTable->removeRow(0);
2979 qDeleteAll(state()->allJobs());
2980 state()->allJobs().clear();
2982 while (state()->getSequence().count())
2983 state()->getSequence().pop_back();
2984 emit sequenceChanged(state()->getSequence());
2987QVariantMap Camera::getAllSettings()
const
2989 QVariantMap settings;
2995 auto name = oneWidget->objectName();
2996 if (name ==
"qt_spinbox_lineedit")
2998 settings.
insert(name, oneWidget->text());
3003 settings.insert(oneWidget->objectName(), oneWidget->currentText());
3007 settings.insert(oneWidget->objectName(), oneWidget->value());
3011 settings.insert(oneWidget->objectName(), oneWidget->value());
3015 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
3019 if (oneWidget->isCheckable())
3020 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
3024 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
3029void Camera::setAllSettings(
const QVariantMap &settings,
const QVariantMap * standAloneSettings)
3033 disconnectSyncSettings();
3035 for (
auto &name : settings.keys())
3041 syncControl(settings, name, comboBox);
3049 syncControl(settings, name, doubleSpinBox);
3057 syncControl(settings, name, spinBox);
3065 syncControl(settings, name, checkbox);
3071 if (groupbox && groupbox->isCheckable())
3073 syncControl(settings, name, groupbox);
3081 syncControl(settings, name, radioButton);
3089 syncControl(settings, name, lineEdit);
3095 for (
auto &key : settings.keys())
3097 auto value = settings[key];
3099 Options::self()->setProperty(key.
toLatin1(), value);
3101 m_settings[key] = value;
3102 m_GlobalSettings[key] = value;
3105 if (standAloneSettings && standAloneSettings->size() > 0)
3107 for (
const auto &k : standAloneSettings->keys())
3108 m_settings[k] = (*standAloneSettings)[k];
3111 emit settingsUpdated(getAllSettings());
3116 const int id = OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText());
3117 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3118 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
3119 Options::setCaptureTrainID(
id);
3122 connectSyncSettings();
3125void Camera::setupOpticalTrainManager()
3127 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Camera::refreshOpticalTrain);
3130 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
3134 ProfileSettings::Instance()->setOneSetting(ProfileSettings::CaptureOpticalTrain,
3135 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
3136 refreshOpticalTrain();
3137 emit trainChanged();
3141void Camera::refreshOpticalTrain()
3143 opticalTrainCombo->blockSignals(
true);
3144 opticalTrainCombo->clear();
3145 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
3146 trainB->setEnabled(
true);
3148 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3149 if (m_standAlone || trainID.
isValid())
3151 auto id = m_standAlone ? Options::captureTrainID() : trainID.toUInt();
3152 Options::setCaptureTrainID(
id);
3155 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
3157 qCWarning(KSTARS_EKOS_CAPTURE) <<
"Optical train doesn't exist for id" << id;
3158 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
3161 auto name = OpticalTrainManager::Instance()->name(
id);
3163 opticalTrainCombo->setCurrentText(name);
3165 process()->refreshOpticalTrain(name);
3171 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3172 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
3173 if (settings.isValid())
3175 auto map = settings.toJsonObject().toVariantMap();
3176 if (map != m_settings)
3178 QVariantMap standAloneSettings = copyStandAloneSettings(m_settings);
3180 setAllSettings(map, &standAloneSettings);
3184 setSettings(m_GlobalSettings);
3187 opticalTrainCombo->blockSignals(
false);
3190void Camera::selectOpticalTrain(QString name)
3192 opticalTrainCombo->setCurrentText(name);
3195void Camera::syncLimitSettings()
3197 m_LimitsUI->enforceStartGuiderDrift->setChecked(Options::enforceStartGuiderDrift());
3198 m_LimitsUI->startGuideDeviation->setValue(Options::startGuideDeviation());
3199 m_LimitsUI->enforceGuideDeviation->setChecked(Options::enforceGuideDeviation());
3200 m_LimitsUI->guideDeviation->setValue(Options::guideDeviation());
3201 m_LimitsUI->guideDeviationReps->setValue(
static_cast<int>(Options::guideDeviationReps()));
3202 m_LimitsUI->enforceAutofocusHFR->setChecked(Options::enforceAutofocusHFR());
3203 m_LimitsUI->hFRThresholdPercentage->setValue(Options::hFRThresholdPercentage());
3204 m_LimitsUI->hFRDeviation->setValue(Options::hFRDeviation());
3205 m_LimitsUI->inSequenceCheckFrames->setValue(Options::inSequenceCheckFrames());
3206 m_LimitsUI->hFRCheckAlgorithm->setCurrentIndex(Options::hFRCheckAlgorithm());
3207 m_LimitsUI->enforceAutofocusOnTemperature->setChecked(Options::enforceAutofocusOnTemperature());
3208 m_LimitsUI->maxFocusTemperatureDelta->setValue(Options::maxFocusTemperatureDelta());
3209 m_LimitsUI->enforceRefocusEveryN->setChecked(Options::enforceRefocusEveryN());
3210 m_LimitsUI->refocusEveryN->setValue(
static_cast<int>(Options::refocusEveryN()));
3211 m_LimitsUI->refocusAfterMeridianFlip->setChecked(Options::refocusAfterMeridianFlip());
3214void Camera::settleSettings()
3216 state()->setDirty(
true);
3217 emit settingsUpdated(getAllSettings());
3219 const int id = OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText());
3220 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3221 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Capture, m_settings);
3222 Options::setCaptureTrainID(
id);
3225void Camera::syncSettings()
3227 QDoubleSpinBox *dsb =
nullptr;
3228 QSpinBox *sb =
nullptr;
3229 QCheckBox *cb =
nullptr;
3230 QGroupBox *gb =
nullptr;
3231 QRadioButton *rb =
nullptr;
3232 QComboBox *cbox =
nullptr;
3233 QLineEdit *le =
nullptr;
3241 value = dsb->
value();
3247 value = sb->
value();
3265 settings().remove(key);
3284 settings()[key] = value;
3285 m_GlobalSettings[key] = value;
3287 Options::self()->setProperty(key.
toLatin1(), value);
3288 m_DebounceTimer.start();
3292void Camera::connectSyncSettings()
3312 if (oneWidget->isCheckable())
3322 if (oneWidget->objectName() ==
"qt_spinbox_lineedit" || oneWidget->isReadOnly())
3331void Camera::disconnectSyncSettings()
3351 if (oneWidget->isCheckable())
3361 if (oneWidget->objectName() ==
"qt_spinbox_lineedit")
3367void Camera::storeTrainKey(
const QString &key,
const QStringList &list)
3369 if (!m_settings.contains(key) || m_settings[key].toStringList() != list)
3371 m_settings[key] =
list;
3372 m_DebounceTimer.start();
3376void Camera::storeTrainKeyString(
const QString &key,
const QString &str)
3378 if (!m_settings.contains(key) || m_settings[key].toString() != str)
3380 m_settings[key] = str;
3381 m_DebounceTimer.start();
3385void Camera::setupFilterManager()
3388 if (filterManager())
3389 filterManager()->disconnect(
this);
3392 Manager::Instance()->createFilterManager(devices()->filterWheel());
3395 Manager::Instance()->getFilterManager(devices()->filterWheel()->getDeviceName(), m_FilterManager);
3397 devices()->setFilterManager(m_FilterManager);
3399 connect(filterManager().
get(), &FilterManager::updated,
this, [
this]()
3401 emit filterManagerUpdated(devices()->filterWheel());
3405 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::newFilterStatus);
3409 filterManager()->refreshFilterModel();
3410 filterManager()->show();
3411 filterManager()->raise();
3414 connect(filterManager().
get(), &FilterManager::failed,
this, [
this]()
3418 appendLogText(
i18n(
"Filter operation failed."));
3424 connect(filterManager().
get(), &FilterManager::newStatus,
this, &Camera::setFilterStatus);
3426 connect(filterManager().
get(), &FilterManager::labelsChanged,
this, [
this]()
3428 FilterPosCombo->clear();
3429 FilterPosCombo->addItems(filterManager()->getFilterLabels());
3430 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3431 updateCurrentFilterPosition();
3432 storeTrainKey(KEY_FILTERS, filterManager()->getFilterLabels());
3435 connect(filterManager().
get(), &FilterManager::positionChanged,
this, [
this]()
3437 FilterPosCombo->setCurrentIndex(filterManager()->getFilterPosition() - 1);
3438 updateCurrentFilterPosition();
3442void Camera::clearFilterManager()
3445 if (m_FilterManager)
3446 m_FilterManager->disconnect(
this);
3449 m_FilterManager.clear();
3450 devices()->clearFilterManager();
3453void Camera::refreshFilterSettings()
3455 FilterPosCombo->clear();
3457 if (!devices()->filterWheel())
3459 FilterPosLabel->setEnabled(
false);
3460 FilterPosCombo->setEnabled(
false);
3461 filterEditB->setEnabled(
false);
3462 filterManagerB->setEnabled(
false);
3464 clearFilterManager();
3468 FilterPosLabel->setEnabled(
true);
3469 FilterPosCombo->setEnabled(
true);
3470 filterEditB->setEnabled(
true);
3471 filterManagerB->setEnabled(
true);
3473 setupFilterManager();
3475 const auto labels = process()->filterLabels();
3476 FilterPosCombo->addItems(labels);
3479 storeTrainKey(KEY_FILTERS, labels);
3481 updateCurrentFilterPosition();
3483 filterEditB->setEnabled(state()->getCurrentFilterPosition() > 0);
3484 filterManagerB->setEnabled(state()->getCurrentFilterPosition() > 0);
3486 FilterPosCombo->setCurrentIndex(state()->getCurrentFilterPosition() - 1);
3489void Camera::updateCurrentFilterPosition()
3491 const QString currentFilterText = FilterPosCombo->itemText(m_FilterManager->getFilterPosition() - 1);
3492 state()->setCurrentFilterPosition(m_FilterManager->getFilterPosition(),
3494 m_FilterManager->getFilterLock(currentFilterText));
3498void Camera::setFilterWheel(QString name)
3504 if (devices()->filterWheel() && devices()->filterWheel()->getDeviceName() == name)
3506 refreshFilterSettings();
3510 auto isConnected = devices()->filterWheel() && devices()->filterWheel()->isConnected();
3511 FilterPosLabel->setEnabled(isConnected);
3512 FilterPosCombo->setEnabled(isConnected);
3513 filterManagerB->setEnabled(isConnected);
3515 refreshFilterSettings();
3517 if (devices()->filterWheel())
3518 emit settingsUpdated(getAllSettings());
3521ISD::Camera *Camera::activeCamera()
3523 return m_DeviceAdaptor->getActiveCamera();
3526QJsonObject Camera::currentScope()
3528 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3529 if (activeCamera() && trainID.
isValid())
3531 auto id = trainID.
toUInt();
3532 auto name = OpticalTrainManager::Instance()->name(
id);
3533 return OpticalTrainManager::Instance()->getScope(name);
3536 return QJsonObject();
3539double Camera::currentReducer()
3541 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::CaptureOpticalTrain);
3542 if (activeCamera() && trainID.
isValid())
3544 auto id = trainID.
toUInt();
3545 auto name = OpticalTrainManager::Instance()->name(
id);
3546 return OpticalTrainManager::Instance()->getReducer(name);
3552double Camera::currentAperture()
3554 auto scope = currentScope();
3556 double focalLength = scope[
"focal_length"].toDouble(-1);
3557 double aperture = scope[
"aperture"].toDouble(-1);
3558 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3561 if (aperture < 0 && focalRatio > 0)
3562 aperture = focalLength * focalRatio;
3567void Camera::updateMeridianFlipStage(MeridianFlipState::MFStage stage)
3570 if (state()->getMeridianFlipState()->getMeridianFlipStage() != stage)
3574 case MeridianFlipState::MF_READY:
3582 case MeridianFlipState::MF_INITIATED:
3583 captureStatusWidget->setStatus(
i18n(
"Meridian Flip..."),
Qt::yellow);
3584 KSNotification::event(QLatin1String(
"MeridianFlipStarted"),
i18n(
"Meridian flip started"), KSNotification::Capture);
3587 case MeridianFlipState::MF_COMPLETED:
3588 captureStatusWidget->setStatus(
i18n(
"Flip complete."),
Qt::yellow);
3597void Camera::openExposureCalculatorDialog()
3599 QCINFO <<
"Instantiating an Exposure Calculator";
3602 double preferredSkyQuality = 20.5;
3604 auto scope = currentScope();
3605 double focalRatio = scope[
"focal_ratio"].toDouble(-1);
3607 auto reducedFocalLength = currentReducer() * scope[
"focal_length"].toDouble(-1);
3608 auto aperture = currentAperture();
3609 auto reducedFocalRatio = (focalRatio > 0 || aperture == 0) ? focalRatio : reducedFocalLength / aperture;
3611 if (devices()->getActiveCamera() !=
nullptr)
3613 QCINFO <<
"set ExposureCalculator preferred camera to active camera id: "
3614 << devices()->getActiveCamera()->getDeviceName();
3617 QPointer<ExposureCalculatorDialog> anExposureCalculatorDialog(
new ExposureCalculatorDialog(
KStars::Instance(),
3618 preferredSkyQuality,
3620 devices()->getActiveCamera()->getDeviceName()));
3622 anExposureCalculatorDialog->show();
3625void Camera::handleScriptsManager()
3627 QMap<ScriptTypes, QString> old_scripts = m_scriptsManager->getScripts();
3631 m_scriptsManager->setScripts(old_scripts);
3634void Camera::showTemperatureRegulation()
3636 if (!devices()->getActiveCamera())
3639 double currentRamp, currentThreshold;
3640 if (!devices()->getActiveCamera()->getTemperatureRegulation(currentRamp, currentThreshold))
3643 double rMin, rMax, rStep, tMin, tMax, tStep;
3645 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_SLOPE", &rMin, &rMax, &rStep);
3646 devices()->getActiveCamera()->getMinMaxStep(
"CCD_TEMP_RAMP",
"RAMP_THRESHOLD", &tMin, &tMax, &tStep);
3648 QLabel rampLabel(
i18nc(
"Maximum temperature variation over time when regulating.",
"Ramp (°C/min):"));
3649 QDoubleSpinBox rampSpin;
3655 "<p>Maximum temperature change per minute when cooling or warming the camera. Set zero to disable."
3656 "<p>This setting is read from and stored in the INDI camera driver configuration."
3659 QLabel thresholdLabel(
i18nc(
"Temperature threshold above which regulation triggers.",
"Threshold (°C):"));
3660 QDoubleSpinBox thresholdSpin;
3664 thresholdSpin.
setValue(currentThreshold);
3666 "<p>Maximum difference between camera and target temperatures triggering regulation."
3667 "<p>This setting is read from and stored in the INDI camera driver configuration."
3671 layout.addRow(&rampLabel, &rampSpin);
3672 layout.addRow(&thresholdLabel, &thresholdSpin);
3674 QPointer<QDialog> dialog =
new QDialog(
this);
3678 dialog->setWindowTitle(
i18nc(
"@title:window",
"Set Temperature Regulation"));
3679 layout.addWidget(&buttonBox);
3680 dialog->setLayout(&
layout);
3681 dialog->setMinimumWidth(300);
3685 if (devices()->getActiveCamera())
3686 devices()->getActiveCamera()->setTemperatureRegulation(rampSpin.
value(), thresholdSpin.
value());
3690void Camera::createDSLRDialog()
3692 m_DSLRInfoDialog.reset(
new DSLRInfo(
this, devices()->getActiveCamera()));
3694 connect(m_DSLRInfoDialog.get(), &DSLRInfo::infoChanged,
this, [
this]()
3696 if (devices()->getActiveCamera())
3697 addDSLRInfo(QString(devices()->getActiveCamera()->getDeviceName()),
3698 m_DSLRInfoDialog->sensorMaxWidth,
3699 m_DSLRInfoDialog->sensorMaxHeight,
3700 m_DSLRInfoDialog->sensorPixelW,
3701 m_DSLRInfoDialog->sensorPixelH);
3704 m_DSLRInfoDialog->show();
3706 emit dslrInfoRequested(devices()->getActiveCamera()->getDeviceName());
3709void Camera::showObserverDialog()
3711 QList<OAL::Observer *> m_observerList;
3713 QStringList observers;
3714 for (
auto &o : m_observerList)
3715 observers << QString(
"%1 %2").arg(o->name(), o->surname());
3717 QDialog observersDialog(
this);
3718 observersDialog.setWindowTitle(
i18nc(
"@title:window",
"Select Current Observer"));
3720 QLabel
label(
i18n(
"Current Observer:"));
3722 QComboBox observerCombo(&observersDialog);
3723 observerCombo.addItems(observers);
3724 observerCombo.setCurrentText(getObserverName());
3727 QPushButton manageObserver(&observersDialog);
3728 manageObserver.setFixedSize(QSize(32, 32));
3731 manageObserver.setToolTip(
i18n(
"Manage Observers"));
3737 QList<OAL::Observer *> m_observerList;
3739 QStringList observers;
3740 for (
auto &o : m_observerList)
3741 observers << QString(
"%1 %2").arg(o->name(), o->surname());
3743 observerCombo.
clear();
3744 observerCombo.addItems(observers);
3745 observerCombo.setCurrentText(getObserverName());
3749 QHBoxLayout *
layout =
new QHBoxLayout;
3750 layout->addWidget(&label);
3751 layout->addWidget(&observerCombo);
3752 layout->addWidget(&manageObserver);
3754 observersDialog.setLayout(
layout);
3756 observersDialog.exec();
3757 setObserverName(observerCombo.currentText());
3760void Camera::onStandAloneShow(QShowEvent * event)
3762 OpticalTrainSettings::Instance()->setOpticalTrainID(Options::captureTrainID());
3763 auto oneSetting = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Capture);
3764 setSettings(oneSetting.toJsonObject().toVariantMap());
3767 QSharedPointer<FilterManager> fm;
3769 captureGainN->setValue(GainSpinSpecialValue);
3770 captureOffsetN->setValue(OffsetSpinSpecialValue);
3772 m_standAloneUseCcdGain =
true;
3773 m_standAloneUseCcdOffset =
true;
3774 if (m_settings.contains(KEY_GAIN_KWD) && m_settings[KEY_GAIN_KWD].toString() ==
"CCD_CONTROLS")
3775 m_standAloneUseCcdGain =
false;
3776 if (m_settings.contains(KEY_OFFSET_KWD) && m_settings[KEY_OFFSET_KWD].toString() ==
"CCD_CONTROLS")
3777 m_standAloneUseCcdOffset =
false;
3783 if (captureGainN->value() != GainSpinSpecialValue)
3784 setGain(captureGainN->value());
3792 if (captureOffsetN->value() != OffsetSpinSpecialValue)
3793 setOffset(captureOffsetN->value());
3799void Camera::setStandAloneGain(
double value)
3801 QMap<QString, QMap<QString, QVariant> > propertyMap = m_customPropertiesDialog->getCustomProperties();
3803 if (m_standAloneUseCcdGain)
3807 QMap<QString, QVariant> ccdGain;
3808 ccdGain[
"GAIN"] = value;
3809 propertyMap[
"CCD_GAIN"] = ccdGain;
3813 propertyMap[
"CCD_GAIN"].
remove(
"GAIN");
3814 if (propertyMap[
"CCD_GAIN"].
size() == 0)
3815 propertyMap.
remove(
"CCD_GAIN");
3822 QMap<QString, QVariant> ccdGain = propertyMap[
"CCD_CONTROLS"];
3823 ccdGain[
"Gain"] = value;
3824 propertyMap[
"CCD_CONTROLS"] = ccdGain;
3828 propertyMap[
"CCD_CONTROLS"].
remove(
"Gain");
3829 if (propertyMap[
"CCD_CONTROLS"].
size() == 0)
3830 propertyMap.
remove(
"CCD_CONTROLS");
3834 m_customPropertiesDialog->setCustomProperties(propertyMap);
3837void Camera::setStandAloneOffset(
double value)
3839 QMap<QString, QMap<QString, QVariant> > propertyMap = m_customPropertiesDialog->getCustomProperties();
3841 if (m_standAloneUseCcdOffset)
3845 QMap<QString, QVariant> ccdOffset;
3846 ccdOffset[
"OFFSET"] = value;
3847 propertyMap[
"CCD_OFFSET"] = ccdOffset;
3851 propertyMap[
"CCD_OFFSET"].
remove(
"OFFSET");
3852 if (propertyMap[
"CCD_OFFSET"].
size() == 0)
3853 propertyMap.
remove(
"CCD_OFFSET");
3860 QMap<QString, QVariant> ccdOffset = propertyMap[
"CCD_CONTROLS"];
3861 ccdOffset[
"Offset"] = value;
3862 propertyMap[
"CCD_CONTROLS"] = ccdOffset;
3866 propertyMap[
"CCD_CONTROLS"].
remove(
"Offset");
3867 if (propertyMap[
"CCD_CONTROLS"].
size() == 0)
3868 propertyMap.
remove(
"CCD_CONTROLS");
3872 m_customPropertiesDialog->setCustomProperties(propertyMap);
3875void Camera::setVideoStreamEnabled(
bool enabled)
3879 liveVideoB->setChecked(
true);
3884 liveVideoB->setChecked(
false);
3890void Camera::setCoolerToggled(
bool enabled)
3892 auto isToggled = (!
enabled && coolerOnB->isChecked()) || (
enabled && coolerOffB->isChecked());
3894 coolerOnB->blockSignals(
true);
3895 coolerOnB->setChecked(
enabled);
3896 coolerOnB->blockSignals(
false);
3898 coolerOffB->blockSignals(
true);
3899 coolerOffB->setChecked(!
enabled);
3900 coolerOffB->blockSignals(
false);
3903 appendLogText(
enabled ?
i18n(
"Cooler is on") :
i18n(
"Cooler is off"));
3906void Camera::setFilterStatus(FilterState filterState)
3908 if (filterState != state()->getFilterManagerState())
3909 QCDEBUG <<
"Filter state changed from" << Ekos::getFilterStatusString(
3910 state()->getFilterManagerState()) <<
"to" << Ekos::getFilterStatusString(filterState);
3913 switch (filterState)
3916 appendLogText(
i18n(
"Changing focus offset by %1 steps...",
3917 filterManager()->getTargetFilterOffset()));
3921 appendLogText(
i18n(
"Changing filter to %1...",
3922 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3925 case FILTER_AUTOFOCUS:
3926 appendLogText(
i18n(
"Auto focus on filter change..."));
3927 clearAutoFocusHFR();
3931 if (state()->getFilterManagerState() == FILTER_CHANGE)
3933 appendLogText(
i18n(
"Filter set to %1.",
3934 FilterPosCombo->itemText(filterManager()->getTargetFilterPosition() - 1)));
3942 state()->setFilterManagerState(filterState);
3945 captureStatusWidget->setFilterState(filterState);
3948void Camera::resetJobs()
3954 if (m_JobUnderEdit ==
true)
3956 SequenceJob * job = state()->allJobs().at(queueTable->currentRow());
3960 updateJobTable(job);
3966 nullptr,
i18n(
"Are you sure you want to reset status of all jobs?"),
i18n(
"Reset job status"),
3972 foreach (SequenceJob * job, state()->allJobs())
3975 updateJobTable(job);
3980 state()->clearCapturedFramesMap();
3983 state()->setIgnoreJobProgress(Options::alwaysResetSequenceWhenStarting());
3986 startB->setEnabled(
true);
3989bool Camera::selectJob(QModelIndex i)
3991 if (i.
row() < 0 || (i.
row() + 1) > state()->allJobs().
size())
3994 SequenceJob * job = state()->allJobs().at(i.
row());
3996 if (job ==
nullptr || job->jobType() == SequenceJob::JOBTYPE_DARKFLAT)
4001 if (state()->isBusy())
4004 if (state()->allJobs().
size() >= 2)
4006 queueUpB->setEnabled(i.
row() > 0);
4007 queueDownB->setEnabled(i.
row() + 1 < state()->allJobs().
size());
4013void Camera::editJob(QModelIndex i)
4016 if (selectJob(i) ==
false)
4019 appendLogText(
i18n(
"Editing job #%1...", i.
row() + 1));
4022 addToQueueB->setToolTip(
i18n(
"Apply job changes."));
4023 removeFromQueueB->setToolTip(
i18n(
"Cancel job changes."));
4026 previewB->setDefault(
false);
4027 addToQueueB->setDefault(
true);
4029 m_JobUnderEdit =
true;
4033void Camera::resetJobEdit(
bool cancelled)
4035 if (cancelled ==
true)
4036 appendLogText(
i18n(
"Editing job canceled."));
4038 m_JobUnderEdit =
false;
4041 addToQueueB->setToolTip(
i18n(
"Add job to sequence queue"));
4042 removeFromQueueB->setToolTip(
i18n(
"Remove job from sequence queue"));
4044 addToQueueB->setDefault(
false);
4045 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.
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
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.
CaptureState
Capture states.
@ CAPTURE_SETTING_ROTATOR
@ CAPTURE_CHANGING_FILTER
@ CAPTURE_SETTING_TEMPERATURE
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
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)
QString name(StandardAction id)
const QList< QKeySequence > & begin()
QString label(StandardShortcut id)
const QList< QKeySequence > & end()
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void doubleClicked(const QModelIndex &index)
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
void 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)
virtual bool event(QEvent *e)
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 restoreState(const QByteArray &state)
Qt::ItemFlags flags() const const
void setFlags(Qt::ItemFlags flags)
QStandardItem * item(int row, int column) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString & insert(qsizetype position, QChar ch)
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)
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