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"), i18n("Filter manager is not initilized yet. Filter wheel missing from train?"), KSNotification::Capture, KSNotification::Alert);
423 emit filterIdChanged(-1);
424 }
425 else
426 emit filterIdChanged(m_FilterManager->getFilterPosition());
427}
428
429void Ekos::CaptureDeviceAdaptor::setFilterChangeFailed()
430{
431 qWarning(KSTARS_EKOS_CAPTURE) << "Failed to change filter wheel to target position!";
432 emit filterIdChanged(-1);
433}
434
435void CaptureDeviceAdaptor::readCurrentState(CaptureState state)
436{
437 switch(state)
438 {
440 if (m_ActiveCamera != nullptr)
441 {
442 double currentTemperature;
443 m_ActiveCamera->getTemperature(&currentTemperature);
444 emit newCCDTemperatureValue(currentTemperature);
445 }
446 break;
448 readRotatorAngle();
449 break;
451 // intentionally left empty since the guider regularly updates the drift
452 break;
453 default:
454 // this should not happen!
455 qWarning(KSTARS_EKOS_CAPTURE) << "Reading device state " << state << " not implemented!";
456 break;
457 }
458}
459
460void CaptureDeviceAdaptor::readCurrentMountParkState()
461{
462 if (m_ActiveMount != nullptr)
463 emit scopeParkStatusChanged(m_ActiveMount->parkStatus());
464}
465
466void CaptureDeviceAdaptor::setCCDTemperature(double temp)
467{
468 if (m_ActiveCamera != nullptr)
469 m_ActiveCamera->setTemperature(temp);
470}
471
472void CaptureDeviceAdaptor::enableCCDBatchMode(bool enable)
473{
474 if (m_ActiveChip != nullptr)
475 m_ActiveChip->setBatchMode(enable);
476}
477
478void CaptureDeviceAdaptor::abortFastExposure()
479{
480 if (m_ActiveCamera != nullptr && m_ActiveChip != nullptr && m_ActiveCamera->isFastExposureEnabled())
481 m_ActiveChip->abortExposure();
482}
483
484double CaptureDeviceAdaptor::cameraGain(QMap<QString, QMap<QString, QVariant> > propertyMap)
485{
486 if (getActiveCamera())
487 {
488 // derive attributes from active camera
489 if (getActiveCamera()->getProperty("CCD_GAIN"))
490 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
491 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
492 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
493 }
494 else // no active camera set, e.g. whien used from the scheduler
495 {
496 // if camera is unknown, use the custom property that is set
497 if (propertyMap.keys().contains("CCD_GAIN"))
498 return propertyMap["CCD_GAIN"].value("GAIN", -1).toDouble();
499 else if(propertyMap.keys().contains("CCD_CONTROLS"))
500 return propertyMap["CCD_CONTROLS"].value("Gain", -1).toDouble();
501 }
502
503 // none found
504 return -1;
505
506}
507
508double CaptureDeviceAdaptor::cameraGain()
509{
510 double value = INVALID_VALUE;
511 if (getActiveCamera() != nullptr)
512 getActiveCamera()->getGain(&value);
513
514 return value;
515}
516
517double CaptureDeviceAdaptor::cameraOffset(QMap<QString, QMap<QString, QVariant> > propertyMap)
518{
519 if (getActiveCamera())
520 {
521 if (getActiveCamera()->getProperty("CCD_OFFSET"))
522 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
523 else if (getActiveCamera()->getProperty("CCD_CONTROLS"))
524 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
525 }
526 else
527 {
528 // if camera is unknown, use the custom property that is set
529 if (propertyMap.keys().contains("CCD_OFFSET"))
530 return propertyMap["CCD_OFFSET"].value("OFFSET", -1).toDouble();
531 else if(propertyMap.keys().contains("CCD_CONTROLS"))
532 return propertyMap["CCD_CONTROLS"].value("Offset", -1).toDouble();
533 }
534 return -1;
535}
536
537double CaptureDeviceAdaptor::cameraOffset()
538{
539 double value = INVALID_VALUE;
540 if (getActiveCamera() != nullptr)
541 getActiveCamera()->getOffset(&value);
542
543 return value;
544}
545
546double CaptureDeviceAdaptor::cameraTemperature()
547{
548 double value = INVALID_VALUE;
549 if (getActiveCamera() != nullptr)
550 getActiveCamera()->getTemperature(&value);
551
552 return value;
553}
554
555void CaptureDeviceAdaptor::setFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy)
556{
557 if (m_FilterManager.isNull() == false && m_ActiveFilterWheel != nullptr)
558 m_FilterManager->setFilterPosition(targetFilterPosition, policy);
559}
560
561void CaptureDeviceAdaptor::clearFilterManager()
562{
563 m_FilterManager.clear();
564}
565
566void CaptureDeviceAdaptor::setFilterManager(const QSharedPointer<FilterManager> &device)
567{
568 // avoid doubled definition
569 if (m_FilterManager == device)
570 return;
571
572 // disconnect old filter manager
573 if (m_FilterManager.isNull() == false)
574 {
575 disconnect(m_FilterManager.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
576 disconnectFilterManager(currentSequenceJobState.data());
577 }
578 //connect new filter manager
579 if (device.isNull() == false)
580 {
581 connect(device.get(), &FilterManager::ready, this, &CaptureDeviceAdaptor::updateFilterPosition);
582 connectFilterManager(currentSequenceJobState.data());
583 }
584
585 m_FilterManager = device;
586}
587
588void CaptureDeviceAdaptor::askManualScopeCover(QString question, QString title, bool light)
589{
590 // do not ask again
591 if (light && m_ManualLightCoveringAsked == true)
592 {
593 emit manualScopeCoverUpdated(true, true, true);
594 return;
595 }
596 else if (!light && m_ManualDarkCoveringAsked == true)
597 {
598 emit manualScopeCoverUpdated(true, true, false);
599 return;
600 }
601
602 // Continue
603 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
604 {
605 emit manualScopeCoverUpdated(true, true, light);
606 KSMessageBox::Instance()->disconnect(this);
607 m_ManualLightCoveringAsked = false;
608 m_ManualLightOpeningAsked = false;
609 m_ManualDarkCoveringAsked = false;
610 m_ManualDarkOpeningAsked = false;
611 if (light)
612 m_ManualLightCoveringAsked = true;
613 else
614 m_ManualDarkCoveringAsked = true;
615 });
616
617 // Cancel
618 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
619 {
620 if (light)
621 m_ManualLightCoveringAsked = false;
622 else
623 m_ManualDarkCoveringAsked = false;
624
625 emit manualScopeCoverUpdated(true, false, light);
626 KSMessageBox::Instance()->disconnect(this);
627 });
628
629 KSMessageBox::Instance()->warningContinueCancel(question, title, Options::manualCoverTimeout());
630
631}
632
633void CaptureDeviceAdaptor::askManualScopeOpen(bool light)
634{
635 // do not ask again
636 if (light && m_ManualLightOpeningAsked == true)
637 {
638 emit manualScopeCoverUpdated(false, true, true);
639 return;
640 }
641 else if (!light && m_ManualDarkOpeningAsked == true)
642 {
643 emit manualScopeCoverUpdated(false, true, false);
644 return;
645 }
646
647 // Continue
648 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this, light]()
649 {
650 m_ManualLightCoveringAsked = false;
651 m_ManualLightOpeningAsked = false;
652 m_ManualDarkCoveringAsked = false;
653 m_ManualDarkOpeningAsked = false;
654
655 if (light)
656 m_ManualLightOpeningAsked = true;
657 else
658 m_ManualDarkOpeningAsked = true;
659
660 emit manualScopeCoverUpdated(false, true, light);
661 KSMessageBox::Instance()->disconnect(this);
662 });
663
664 // Cancel
665 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this, light]()
666 {
667 if (light)
668 m_ManualLightOpeningAsked = false;
669 else
670 m_ManualDarkOpeningAsked = false;
671 emit manualScopeCoverUpdated(false, false, light);
672 KSMessageBox::Instance()->disconnect(this);
673 });
674
675 KSMessageBox::Instance()->warningContinueCancel(i18n("Remove cover from the telescope in order to continue."),
676 i18n("Telescope Covered"), Options::manualCoverTimeout());
677
678}
679
680void CaptureDeviceAdaptor::setLightBoxLight(bool on)
681{
682 m_ActiveLightBox->setLightEnabled(on);
683 emit lightBoxLight(on);
684}
685
686void CaptureDeviceAdaptor::parkDustCap(bool park)
687{
688 // park
689 if (park == true)
690 if (m_ActiveDustCap->park())
691 emit dustCapStatusChanged(ISD::DustCap::CAP_PARKING);
692 else
693 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
694 // unpark
695 else if (m_ActiveDustCap->unpark())
696 emit dustCapStatusChanged(ISD::DustCap::CAP_UNPARKING);
697 else
698 emit dustCapStatusChanged(ISD::DustCap::CAP_ERROR);
699}
700
701void CaptureDeviceAdaptor::slewTelescope(SkyPoint &target)
702{
703 if (m_ActiveMount != nullptr)
704 {
705 m_ActiveMount->Slew(&target);
706 emit scopeStatusChanged(ISD::Mount::MOUNT_SLEWING);
707 }
708}
709
710void CaptureDeviceAdaptor::setScopeTracking(bool on)
711{
712 if (m_ActiveMount != nullptr)
713 {
714 m_ActiveMount->setTrackEnabled(on);
715 emit scopeStatusChanged(on ? ISD::Mount::MOUNT_TRACKING : ISD::Mount::MOUNT_IDLE);
716 }
717}
718
719void CaptureDeviceAdaptor::setScopeParked(bool parked)
720{
721 if (m_ActiveMount != nullptr)
722 {
723 if (parked == true)
724 {
725 if (m_ActiveMount->park())
726 emit scopeStatusChanged(ISD::Mount::MOUNT_PARKING);
727 else
728 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
729 }
730 else
731 {
732 if (m_ActiveMount->unpark() == false)
733 emit scopeStatusChanged(ISD::Mount::MOUNT_ERROR);
734 }
735 }
736}
737
738void CaptureDeviceAdaptor::setDomeParked(bool parked)
739{
740 if (m_ActiveDome != nullptr)
741 {
742 if (parked == true)
743 {
744 if (m_ActiveDome->park())
745 emit domeStatusChanged(ISD::Dome::DOME_PARKING);
746 else
747 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
748 }
749 else
750 {
751 if (m_ActiveDome->unpark() == false)
752 emit domeStatusChanged(ISD::Dome::DOME_ERROR);
753 }
754 }
755
756}
757
758void CaptureDeviceAdaptor::flatSyncFocus(int targetFilterID)
759{
760 if (getFilterManager()->syncAbsoluteFocusPosition(targetFilterID - 1))
761 emit flatSyncFocusChanged(true);
762 else
763 emit flatSyncFocusChanged(false);
764}
765
766void CaptureDeviceAdaptor::queryHasShutter()
767{
768 if (m_ActiveCamera == nullptr)
769 {
770 emit hasShutter(false);
771 return;
772 }
773 QStringList shutterfulCCDs = Options::shutterfulCCDs();
774 QStringList shutterlessCCDs = Options::shutterlessCCDs();
775 QString deviceName = m_ActiveCamera->getDeviceName();
776
777 bool shutterFound = shutterfulCCDs.contains(deviceName);
778 // FIXME: what about || (captureISOS && captureISOS->count() > 0?
779 bool noShutterFound = shutterlessCCDs.contains(deviceName);
780
781 if (shutterFound == true)
782 emit hasShutter(true);
783 else if (noShutterFound == true)
784 emit hasShutter(false);
785 else
786 {
787 // If we have no information, we ask before we proceed.
788 QString deviceName = m_ActiveCamera->getDeviceName();
789 // Yes, has shutter
790 connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
791 {
792 KSMessageBox::Instance()->disconnect(this);
793 QStringList shutterfulCCDs = Options::shutterfulCCDs();
794 shutterfulCCDs.append(m_ActiveCamera->getDeviceName());
795 Options::setShutterfulCCDs(shutterfulCCDs);
796 emit hasShutter(true);
797 });
798 // No, has no shutter
799 connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
800 {
801 KSMessageBox::Instance()->disconnect(this);
802 QStringList shutterlessCCDs = Options::shutterlessCCDs();
803 shutterlessCCDs.append(m_ActiveCamera->getDeviceName());
804 Options::setShutterlessCCDs(shutterlessCCDs);
805 emit hasShutter(false);
806 });
807
808 KSMessageBox::Instance()->questionYesNo(i18n("Does %1 have a shutter?", deviceName),
809 i18n("Dark Exposure"));
810 }
811}
812
813} // 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 Mar 28 2025 11:57:24 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.