Kstars

capturedeviceadaptor.cpp
1/* Ekos commands for the capture module
2 SPDX-FileCopyrightText: Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "capturedeviceadaptor.h"
8
9#include "ksmessagebox.h"
10#include "Options.h"
11#include "indi/indistd.h"
12#include "ekos_capture_debug.h"
13#include "sequencejobstate.h"
14
15#include "indi/indicamera.h"
16#include "indi/indidustcap.h"
17#include "indi/indidome.h"
18#include "indi/indilightbox.h"
19#include "indi/indimount.h"
20#include "indi/indirotator.h"
21#include "ekos/auxiliary/rotatorutils.h"
22#include "ksnotification.h"
23
24namespace Ekos
25{
26
27
28void CaptureDeviceAdaptor::connectDome(SequenceJobState *state)
29{
30 if (state == nullptr)
31 return;
32
33 connect(state, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
34 connect(this, &CaptureDeviceAdaptor::domeStatusChanged, state, &SequenceJobState::domeStatusChanged);
35}
36
37void CaptureDeviceAdaptor::disconnectDome(SequenceJobState *state)
38{
39 if (state == nullptr)
40 return;
41
42 disconnect(state, &SequenceJobState::setDomeParked, this, &CaptureDeviceAdaptor::setDomeParked);
43 disconnect(this, &CaptureDeviceAdaptor::domeStatusChanged, state, &SequenceJobState::domeStatusChanged);
44}
45
46void CaptureDeviceAdaptor::setCurrentSequenceJobState(QSharedPointer<SequenceJobState> jobState)
47{
48 // clear old connections
49 disconnectDevices(currentSequenceJobState.data());
50 // add new connections
51 connectRotator(jobState.data());
52 connectFilterManager(jobState.data());
53 connectActiveCamera(jobState.data());
54 connectMount(jobState.data());
55 connectDome(jobState.data());
56 connectDustCap(jobState.data());
57 currentSequenceJobState = jobState;
58
59}
60
61void CaptureDeviceAdaptor::setDustCap(ISD::DustCap *device)
62{
63 disconnectDustCap(currentSequenceJobState.data());
64 m_ActiveDustCap = device;
65 connectDustCap(currentSequenceJobState.data());
66}
67
68void CaptureDeviceAdaptor::disconnectDevices(SequenceJobState *state)
69{
70 disconnectRotator(state);
71 disconnectFilterManager(state);
72 disconnectActiveCamera(state);
73 disconnectMount(state);
74 disconnectDome(state);
75 disconnectDustCap(state);
76}
77
78
79
80
81
82void CaptureDeviceAdaptor::connectDustCap(SequenceJobState *state)
83{
84 if (m_ActiveDustCap != nullptr)
85 connect(m_ActiveDustCap, &ISD::DustCap::newStatus, this, &CaptureDeviceAdaptor::dustCapStatusChanged);
86
87 if (state == nullptr)
88 return;
89
90 connect(state, &SequenceJobState::askManualScopeCover, this, &CaptureDeviceAdaptor::askManualScopeCover);
91 connect(state, &SequenceJobState::askManualScopeOpen, this, &CaptureDeviceAdaptor::askManualScopeOpen);
92 connect(state, &SequenceJobState::setLightBoxLight, this, &CaptureDeviceAdaptor::setLightBoxLight);
93 connect(state, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
94
95 connect(this, &CaptureDeviceAdaptor::manualScopeCoverUpdated, state, &SequenceJobState::updateManualScopeCover);
96 connect(this, &CaptureDeviceAdaptor::lightBoxLight, state, &SequenceJobState::lightBoxLight);
97 connect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, state, &SequenceJobState::dustCapStateChanged);
98}
99
100void CaptureDeviceAdaptor::disconnectDustCap(SequenceJobState *state)
101{
102 if (m_ActiveDustCap != nullptr)
103 disconnect(m_ActiveDustCap, nullptr, this, nullptr);
104
105 if (state == nullptr)
106 return;
107
108 disconnect(state, &SequenceJobState::askManualScopeCover, this, &CaptureDeviceAdaptor::askManualScopeCover);
109 disconnect(state, &SequenceJobState::askManualScopeOpen, this, &CaptureDeviceAdaptor::askManualScopeOpen);
110 disconnect(state, &SequenceJobState::setLightBoxLight, this, &CaptureDeviceAdaptor::setLightBoxLight);
111 disconnect(state, &SequenceJobState::parkDustCap, this, &CaptureDeviceAdaptor::parkDustCap);
112
113 disconnect(this, &CaptureDeviceAdaptor::manualScopeCoverUpdated, state, &SequenceJobState::updateManualScopeCover);
114 disconnect(this, &CaptureDeviceAdaptor::lightBoxLight, state, &SequenceJobState::lightBoxLight);
115 disconnect(this, &CaptureDeviceAdaptor::dustCapStatusChanged, state, &SequenceJobState::dustCapStateChanged);
116}
117
118void CaptureDeviceAdaptor::setMount(ISD::Mount *device)
119{
120 if (m_ActiveMount == device)
121 return;
122
123 // clean up old connections
124 if (m_ActiveMount != nullptr)
125 {
126 disconnect(m_ActiveMount, nullptr, this, nullptr);
127 disconnectMount(currentSequenceJobState.data());
128 }
129 // connect new device
130 if (device != nullptr)
131 {
132 connect(device, &ISD::Mount::newStatus, this, &CaptureDeviceAdaptor::scopeStatusChanged);
133 connect(device, &ISD::Mount::pierSideChanged, this, &CaptureDeviceAdaptor::pierSideChanged);
134 connect(device, &ISD::Mount::newParkStatus, this, &CaptureDeviceAdaptor::scopeParkStatusChanged);
135 connectMount(currentSequenceJobState.data());
136
137 // update mount states
138 emit pierSideChanged(device->pierSide());
139 emit scopeParkStatusChanged(device->parkStatus());
140 }
141
142 m_ActiveMount = device;
143}
144
145void CaptureDeviceAdaptor::connectMount(SequenceJobState *state)
146{
147 if (state == nullptr)
148 return;
149
150 connect(state, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
151 connect(state, &SequenceJobState::setScopeTracking, this, &CaptureDeviceAdaptor::setScopeTracking);
152 connect(state, &SequenceJobState::readCurrentMountParkState, this, &CaptureDeviceAdaptor::readCurrentMountParkState);
153 connect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
154
155 connect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
156 connect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
157}
158
159void CaptureDeviceAdaptor::disconnectMount(SequenceJobState *state)
160{
161 if (state == nullptr)
162 return;
163
164 disconnect(state, &SequenceJobState::slewTelescope, this, &CaptureDeviceAdaptor::slewTelescope);
165 disconnect(state, &SequenceJobState::setScopeTracking, this, &CaptureDeviceAdaptor::setScopeTracking);
166 disconnect(state, &SequenceJobState::setScopeParked, this, &CaptureDeviceAdaptor::setScopeParked);
167
168 disconnect(this, &CaptureDeviceAdaptor::scopeStatusChanged, state, &SequenceJobState::scopeStatusChanged);
169 disconnect(this, &CaptureDeviceAdaptor::scopeParkStatusChanged, state, &SequenceJobState::scopeParkStatusChanged);
170}
171
172void CaptureDeviceAdaptor::setDome(ISD::Dome *device)
173{
174 if (m_ActiveDome == device)
175 return;
176
177 // clean up old connections
178 if (m_ActiveDome != nullptr)
179 {
180 disconnect(m_ActiveDome, nullptr, this, nullptr);
181 disconnectDome(currentSequenceJobState.data());
182 }
183 // connect new device
184 if (device != nullptr)
185 {
186 connect(device, &ISD::Dome::newStatus, this, &CaptureDeviceAdaptor::domeStatusChanged);
187 connectDome(currentSequenceJobState.data());
188 }
189
190 m_ActiveDome = device;
191}
192
193void CaptureDeviceAdaptor::setRotator(ISD::Rotator *device)
194{
195 // do nothing if *real* rotator is already connected
196 if ((m_ActiveRotator == device) && (device != nullptr))
197 return;
198
199 // clean up old connections
200 if (m_ActiveRotator != nullptr)
201 {
202 m_ActiveRotator->disconnect(this);
203 disconnectRotator(currentSequenceJobState.data());
204 }
205
206 m_ActiveRotator = device;
207
208 // connect new device
209 if (m_ActiveRotator != nullptr)
210 {
211 connect(m_ActiveRotator, &ISD::Rotator::newAbsoluteAngle, this, &CaptureDeviceAdaptor::newRotatorAngle,
213 connect(m_ActiveRotator, &ISD::Rotator::reverseToggled, this, &CaptureDeviceAdaptor::rotatorReverseToggled,
215 connectRotator(currentSequenceJobState.data());
216
217 emit newRotator(device->getDeviceName());
218 }
219 else
220 emit newRotator(""); // no real rotator present, so check if user wants to use "manual rotator"
221
222}
223
224void CaptureDeviceAdaptor::connectRotator(SequenceJobState *state)
225{
226 if (state == nullptr)
227 return;
228
229 connect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle,
231 connect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
232}
233
234void CaptureDeviceAdaptor::disconnectRotator(SequenceJobState *state)
235{
236 if (state == nullptr)
237 return;
238
239 disconnect(state, &SequenceJobState::setRotatorAngle, this, &CaptureDeviceAdaptor::setRotatorAngle);
240 disconnect(this, &CaptureDeviceAdaptor::newRotatorAngle, state, &SequenceJobState::setCurrentRotatorPositionAngle);
241}
242
243void CaptureDeviceAdaptor::setRotatorAngle(double rawAngle)
244{
245 if (m_ActiveRotator != nullptr && m_ActiveRotator->setAbsoluteAngle(rawAngle))
246 {
247 RotatorUtils::Instance()->initTimeFrame(rawAngle);
248 qCInfo(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to" << rawAngle << "degrees.";
249 }
250 else
251 qCWarning(KSTARS_EKOS_CAPTURE) << "Setting rotator angle to " << rawAngle
252 << "failed due to missing or unresponsive rotator.";
253}
254
255double CaptureDeviceAdaptor::getRotatorAngle()
256{
257 if (m_ActiveRotator != nullptr)
258 return m_ActiveRotator->absoluteAngle();
259 else
260 return 0;
261}
262
263IPState CaptureDeviceAdaptor::getRotatorAngleState()
264{
265 if (m_ActiveRotator != nullptr)
266 return m_ActiveRotator->absoluteAngleState();
267 else
268 return IPS_ALERT;
269}
270
271void CaptureDeviceAdaptor::reverseRotator(bool toggled)
272{
273 if (m_ActiveRotator != nullptr)
274 {
275 m_ActiveRotator->setReversed(toggled);
276 m_ActiveRotator->setConfig(SAVE_CONFIG);
277 }
278}
279
280void CaptureDeviceAdaptor::readRotatorAngle()
281{
282 if (m_ActiveRotator != nullptr)
283 emit newRotatorAngle(m_ActiveRotator->absoluteAngle(), m_ActiveRotator->absoluteAngleState());
284}
285
286
287
288void CaptureDeviceAdaptor::setActiveCamera(ISD::Camera *device)
289{
290 if (m_ActiveCamera == device)
291 return;
292
293 // disconnect device events if the new device is not empty
294 if (m_ActiveCamera != nullptr)
295 {
296 m_ActiveCamera->disconnect(this);
297 disconnectActiveCamera(currentSequenceJobState.data());
298
299 }
300
301 // store the link to the new device
302 m_ActiveCamera = device;
303
304 // connect device events if the new device is not empty
305 if (m_ActiveCamera != nullptr)
306 {
307 // publish device events
308 connect(m_ActiveCamera, &ISD::Camera::newTemperatureValue, this,
309 &CaptureDeviceAdaptor::newCCDTemperatureValue, Qt::UniqueConnection);
310 connect(m_ActiveCamera, &ISD::ConcreteDevice::Connected, this, [this]()
311 {
312 emit CameraConnected(true);
313 });
314 connect(m_ActiveCamera, &ISD::ConcreteDevice::Disconnected, this, [this]()
315 {
316 emit CameraConnected(false);
317 });
318
319 if (m_ActiveCamera->hasGuideHead())
320 addGuideHead(device);
321 }
322 connectActiveCamera(currentSequenceJobState.data());
323
324 // communicate new camera
325 emit newCamera(device == nullptr ? "" : device->getDeviceName());
326}
327
328void CaptureDeviceAdaptor::setFilterWheel(ISD::FilterWheel *device)
329{
330 if (m_ActiveFilterWheel == device)
331 return;
332
333 // disconnect device events if the new device is not empty
334 if (m_ActiveFilterWheel != nullptr)
335 m_ActiveFilterWheel->disconnect(this);
336
337 // store the link to the new device
338 m_ActiveFilterWheel = device;
339
340 // connect device events if the new device is not empty
341 if (m_ActiveFilterWheel != nullptr)
342 {
343 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Connected, this, [this]()
344 {
345 emit FilterWheelConnected(true);
346 });
347 connect(m_ActiveFilterWheel, &ISD::ConcreteDevice::Disconnected, this, [this]()
348 {
349 emit FilterWheelConnected(false);
350 });
351 }
352
353 // communicate new device
354 emit newFilterWheel(device == nullptr ? "" : device->getDeviceName());
355}
356
357void CaptureDeviceAdaptor::connectActiveCamera(SequenceJobState *state)
358{
359 if (state == nullptr)
360 return;
361
362 //connect state machine to device adaptor
363 connect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
364 connect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
365 connect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
366
367 // forward own events to the state machine
368 connect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
369 connect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
370 connect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature,
372}
373
374void CaptureDeviceAdaptor::disconnectActiveCamera(SequenceJobState *state)
375{
376 if (state == nullptr)
377 return;
378
379 disconnect(state, &SequenceJobState::setCCDTemperature, this, &CaptureDeviceAdaptor::setCCDTemperature);
380 disconnect(state, &SequenceJobState::setCCDBatchMode, this, &CaptureDeviceAdaptor::enableCCDBatchMode);
381 disconnect(state, &SequenceJobState::queryHasShutter, this, &CaptureDeviceAdaptor::queryHasShutter);
382
383 disconnect(this, &CaptureDeviceAdaptor::flatSyncFocusChanged, state, &SequenceJobState::flatSyncFocusChanged);
384 disconnect(this, &CaptureDeviceAdaptor::hasShutter, state, &SequenceJobState::hasShutter);
385 disconnect(this, &CaptureDeviceAdaptor::newCCDTemperatureValue, state, &SequenceJobState::setCurrentCCDTemperature);
386}
387
388void CaptureDeviceAdaptor::connectFilterManager(SequenceJobState *state)
389{
390 if (state == nullptr)
391 return;
392
393 connect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
394 connect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
395 // JEE Make this signal a QueuedConnection to avoid a loop between Capture and FilterManager. This loop can occur where
396 // Capture thinks a filter change or Autofocus is required so signals FilterManager. FilterManager then determines what
397 // is required and if its nothing then immediately signals done to Capture.
398 connect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID, Qt::QueuedConnection);
399
400 if (m_FilterManager.isNull() == false)
401 connect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
402}
403
404void CaptureDeviceAdaptor::disconnectFilterManager(SequenceJobState *state)
405{
406 if (state == nullptr)
407 return;
408
409 disconnect(state, &SequenceJobState::readFilterPosition, this, &CaptureDeviceAdaptor::updateFilterPosition);
410 disconnect(state, &SequenceJobState::changeFilterPosition, this, &CaptureDeviceAdaptor::setFilterPosition);
411 disconnect(this, &CaptureDeviceAdaptor::filterIdChanged, state, &SequenceJobState::setCurrentFilterID);
412
413 if (m_FilterManager.isNull() == false)
414 disconnect(m_FilterManager.get(), &FilterManager::newStatus, state, &SequenceJobState::setFilterStatus);
415}
416
417void Ekos::CaptureDeviceAdaptor::updateFilterPosition()
418{
419 if (m_FilterManager.isNull())
420 {
421 qCritical(KSTARS_EKOS_CAPTURE) << "Filter manager is not initialized yet. Filter wheel missing from train?";
422 KSNotification::event(QLatin1String("CaptureFailed"),
423 i18n("Filter manager is not initilized yet. Filter wheel missing from train?"), KSNotification::Capture,
424 KSNotification::Alert);
425 emit filterIdChanged(-1);
426 }
427 else
428 emit filterIdChanged(m_FilterManager->getFilterPosition());
429}
430
431void Ekos::CaptureDeviceAdaptor::setFilterChangeFailed()
432{
433 qWarning(KSTARS_EKOS_CAPTURE) << "Failed to change filter wheel to target position!";
434 emit filterIdChanged(-1);
435}
436
437void CaptureDeviceAdaptor::readCurrentState(CaptureState state)
438{
439 switch(state)
440 {
442 if (m_ActiveCamera != nullptr)
443 {
444 double currentTemperature;
445 m_ActiveCamera->getTemperature(&currentTemperature);
446 emit newCCDTemperatureValue(currentTemperature);
447 }
448 break;
450 readRotatorAngle();
451 break;
453 // intentionally left empty since the guider regularly updates the drift
454 break;
455 default:
456 // this should not happen!
457 qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
458 break;
459 }
460}
461
462void CaptureDeviceAdaptor::readCurrentMountParkState()
463{
464 if (m_ActiveMount != nullptr)
465 emit scopeParkStatusChanged(m_ActiveMount->parkStatus());
466}
467
468void CaptureDeviceAdaptor::setCCDTemperature(double temp)
469{
470 if (m_ActiveCamera != nullptr)
471 m_ActiveCamera->setTemperature(temp);
472}
473
474void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
475{
476 if (m_ActiveChip != nullptr)
477 m_ActiveChip->setBatchMode(enable);
478}
479
480void CaptureDeviceAdaptor::abortFastExposure()
481{
482 if (m_ActiveCamera != nullptr && m_ActiveChip != nullptr && m_ActiveCamera->isFastExposureEnabled())
483 m_ActiveChip->abortExposure();
484}
485
486double CaptureDeviceAdaptor::cameraGain(QMap<QString, QMap<QString, QVariant> > propertyMap)
487{
488 if (getActiveCamera())
489 {
490 // derive attributes from active camera
491 if (getActiveCamera()->getProperty("CCD_GAIN"))
492 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
493 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
494 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
495 }
496 else // no active camera set, e.g. whien used from the scheduler
497 {
498 // if camera is unknown, use the custom property that is set
499 if (propertyMap.keys().contains("CCD_GAIN"))
500 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
501 else if(propertyMap.keys().contains("CCD_CONTROLS"))
502 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
503 }
504
505 // none found
506 return -1;
507
508}
509
510double CaptureDeviceAdaptor::cameraGain()
511{
512 double value = INVALID_VALUE;
513 if (getActiveCamera() != nullptr)
514 getActiveCamera()->getGain(&value);
515
516 return value;
517}
518
519double CaptureDeviceAdaptor::cameraOffset(QMap<QString, QMap<QString, QVariant> > propertyMap)
520{
521 if (getActiveCamera())
522 {
523 if (getActiveCamera()->getProperty("CCD_OFFSET"))
524 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
525 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
526 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
527 }
528 else
529 {
530 // if camera is unknown, use the custom property that is set
531 if (propertyMap.keys().contains("CCD_OFFSET"))
532 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
533 else if(propertyMap.keys().contains("CCD_CONTROLS"))
534 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
535 }
536 return -1;
537}
538
539double CaptureDeviceAdaptor::cameraOffset()
540{
541 double value = INVALID_VALUE;
542 if (getActiveCamera() != nullptr)
543 getActiveCamera()->getOffset(&value);
544
545 return value;
546}
547
548double CaptureDeviceAdaptor::cameraTemperature()
549{
550 double value = INVALID_VALUE;
551 if (getActiveCamera() != nullptr)
552 getActiveCamera()->getTemperature(&value);
553
554 return value;
555}
556
557void CaptureDeviceAdaptor::setFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy)
558{
559 if (m_FilterManager.isNull() == false && m_ActiveFilterWheel != nullptr)
560 m_FilterManager->setFilterPosition(targetFilterPosition, policy);
561}
562
563void CaptureDeviceAdaptor::clearFilterManager()
564{
565 m_FilterManager.clear();
566}
567
568void CaptureDeviceAdaptor::setFilterManager(const QSharedPointer<FilterManager> &device)
569{
570 // avoid doubled definition
571 if (m_FilterManager == device)
572 return;
573
574 // disconnect old filter manager
575 if (m_FilterManager.isNull() == false)
576 {
577 disconnect(m_FilterManager.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
578 disconnectFilterManager(currentSequenceJobState.data());
579 }
580 //connect new filter manager
581 if (device.isNull() == false)
582 {
583 connect(device.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
584 connectFilterManager(currentSequenceJobState.data());
585 }
586
587 m_FilterManager = device;
588}
589
590void CaptureDeviceAdaptor::askManualScopeCover(QString question, QString title, bool light)
591{
592 // do not ask again
593 if (light && m_ManualLightCoveringAsked == true)
594 {
595 emit manualScopeCoverUpdated(true, true, true);
596 return;
597 }
598 else if (!light && m_ManualDarkCoveringAsked == true)
599 {
600 emit manualScopeCoverUpdated(true, true, false);
601 return;
602 }
603
604 // Continue
605 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
606 {
607 emit manualScopeCoverUpdated(true, true, light);
608 KSMessageBox::Instance()->disconnect(this);
609 m_ManualLightCoveringAsked = false;
610 m_ManualLightOpeningAsked = false;
611 m_ManualDarkCoveringAsked = false;
612 m_ManualDarkOpeningAsked = false;
613 if (light)
614 m_ManualLightCoveringAsked = true;
615 else
616 m_ManualDarkCoveringAsked = true;
617 });
618
619 // Cancel
620 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
621 {
622 if (light)
623 m_ManualLightCoveringAsked = false;
624 else
625 m_ManualDarkCoveringAsked = false;
626
627 emit manualScopeCoverUpdated(true, false, light);
628 KSMessageBox::Instance()->disconnect(this);
629 });
630
631 KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
632
633}
634
635void CaptureDeviceAdaptor::askManualScopeOpen(bool light)
636{
637 // do not ask again
638 if (light && m_ManualLightOpeningAsked == true)
639 {
640 emit manualScopeCoverUpdated(false, true, true);
641 return;
642 }
643 else if (!light && m_ManualDarkOpeningAsked == true)
644 {
645 emit manualScopeCoverUpdated(false, true, false);
646 return;
647 }
648
649 // Continue
650 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
651 {
652 m_ManualLightCoveringAsked = false;
653 m_ManualLightOpeningAsked = false;
654 m_ManualDarkCoveringAsked = false;
655 m_ManualDarkOpeningAsked = false;
656
657 if (light)
658 m_ManualLightOpeningAsked = true;
659 else
660 m_ManualDarkOpeningAsked = true;
661
662 emit manualScopeCoverUpdated(false, true, light);
663 KSMessageBox::Instance()->disconnect(this);
664 });
665
666 // Cancel
667 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
668 {
669 if (light)
670 m_ManualLightOpeningAsked = false;
671 else
672 m_ManualDarkOpeningAsked = false;
673 emit manualScopeCoverUpdated(false, false, light);
674 KSMessageBox::Instance()->disconnect(this);
675 });
676
677 KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
678 i18n("Telescope Covered"), Options::manualCoverTimeout());
679
680}
681
682void CaptureDeviceAdaptor::setLightBoxLight(bool on)
683{
684 m_ActiveLightBox->setLightEnabled(on);
685 emit lightBoxLight(on);
686}
687
688void CaptureDeviceAdaptor::parkDustCap(bool park)
689{
690 // park
691 if (park == true)
692 if (m_ActiveDustCap->park())
693 emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
694 else
695 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
696 // unpark
697 else if (m_ActiveDustCap->unpark())
698 emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
699 else
700 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
701}
702
703void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
704{
705 if (m_ActiveMount != nullptr)
706 {
707 m_ActiveMount->Slew(&target);
708 emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
709 }
710}
711
712void CaptureDeviceAdaptor::setScopeTracking(bool on)
713{
714 if (m_ActiveMount != nullptr)
715 {
716 m_ActiveMount->setTrackEnabled(on);
717 emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
718 }
719}
720
721void CaptureDeviceAdaptor::setScopeParked(bool parked)
722{
723 if (m_ActiveMount != nullptr)
724 {
725 if (parked == true)
726 {
727 if (m_ActiveMount->park())
728 emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
729 else
730 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
731 }
732 else
733 {
734 if (m_ActiveMount->unpark() == false)
735 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
736 }
737 }
738}
739
740void CaptureDeviceAdaptor::setDomeParked(bool parked)
741{
742 if (m_ActiveDome != nullptr)
743 {
744 if (parked == true)
745 {
746 if (m_ActiveDome->park())
747 emit domeStatusChanged(ISD::Dome::DOME_PARKING);
748 else
749 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
750 }
751 else
752 {
753 if (m_ActiveDome->unpark() == false)
754 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
755 }
756 }
757
758}
759
760void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
761{
762 if (m_FilterManager.isNull() || m_FilterManager->syncAbsoluteFocusPosition(targetFilterID - 1))
763 emit flatSyncFocusChanged(true);
764 else
765 emit flatSyncFocusChanged(false);
766}
767
768void CaptureDeviceAdaptor::queryHasShutter()
769{
770 if (m_ActiveCamera == nullptr)
771 {
772 emit hasShutter(false);
773 return;
774 }
775 QStringList shutterfulCCDs = Options::shutterfulCCDs();
776 QStringList shutterlessCCDs = Options::shutterlessCCDs();
777 QString deviceName = m_ActiveCamera->getDeviceName();
778
779 bool shutterFound = shutterfulCCDs.contains(deviceName);
780 // FIXME: what about || (captureISOS && captureISOS->count() > 0?
781 bool noShutterFound = shutterlessCCDs.contains(deviceName);
782
783 if (shutterFound == true)
784 emit hasShutter(true);
785 else if (noShutterFound == true)
786 emit hasShutter(false);
787 else
788 {
789 // If we have no information, we ask before we proceed.
790 QString deviceName = m_ActiveCamera->getDeviceName();
791 // Yes, has shutter
792 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
793 {
794 KSMessageBox::Instance()->disconnect(this);
795 QStringList shutterfulCCDs = Options::shutterfulCCDs();
796 shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
797 Options::setShutterfulCCDs(shutterfulCCDs);
798 emit hasShutter(true);
799 });
800 // No, has no shutter
801 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
802 {
803 KSMessageBox::Instance()->disconnect(this);
804 QStringList shutterlessCCDs = Options::shutterlessCCDs();
805 shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
806 Options::setShutterlessCCDs(shutterlessCCDs);
807 emit hasShutter(false);
808 });
809
810 KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
811 i18n("Dark Exposure"));
812 }
813}
814
815} // namespace
void newStatus(ISD::Mount::Status status)
Change in the mount status.
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
CaptureState
Capture states.
Definition ekos.h:92
@ CAPTURE_GUIDER_DRIFT
Definition ekos.h:106
@ CAPTURE_SETTING_ROTATOR
Definition ekos.h:108
@ CAPTURE_SETTING_TEMPERATURE
Definition ekos.h:107
QCA_EXPORT QVariant getProperty(const QString &name)
void accepted()
void rejected()
void append(QList< T > &&value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
T * data() const const
T * get() const const
bool isNull() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
UniqueConnection
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 11:58:34 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.