Kstars

filtermanager.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "filtermanager.h"
8 #include <kstars_debug.h>
9 
10 #include "indi_debug.h"
11 #include "kstarsdata.h"
12 #include "kstars.h"
13 #include "Options.h"
14 #include "auxiliary/kspaths.h"
15 #include "auxiliary/ksmessagebox.h"
16 #include "ekos/auxiliary/filterdelegate.h"
17 
18 #include <QTimer>
19 #include <QSqlTableModel>
20 #include <QSqlDatabase>
21 #include <QSqlRecord>
22 
23 #include <basedevice.h>
24 
25 #include <algorithm>
26 
27 namespace Ekos
28 {
29 
30 FilterManager::FilterManager() : QDialog(KStars::Instance())
31 {
32 #ifdef Q_OS_OSX
33  setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
34 #endif
35 
36  setupUi(this);
37 
38  connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
39  connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
40 
41  QSqlDatabase userdb = QSqlDatabase::cloneDatabase(KStarsData::Instance()->userdb()->GetDatabase(), "filter_db");
42  userdb.open();
43 
44  kcfg_FlatSyncFocus->setChecked(Options::flatSyncFocus());
45  connect(kcfg_FlatSyncFocus, &QCheckBox::toggled, [this]()
46  {
47  Options::setFlatSyncFocus(kcfg_FlatSyncFocus->isChecked());
48  });
49 
50  filterModel = new QSqlTableModel(this, userdb);
51  filterView->setModel(filterModel);
52 
53  // No Edit delegate
54  noEditDelegate = new NotEditableDelegate(filterView);
55  filterView->setItemDelegateForColumn(4, noEditDelegate);
56 
57  // Exposure delegate
58  exposureDelegate = new ExposureDelegate(filterView);
59  filterView->setItemDelegateForColumn(5, exposureDelegate);
60 
61  // Offset delegate
62  offsetDelegate = new OffsetDelegate(filterView);
63  filterView->setItemDelegateForColumn(6, offsetDelegate);
64 
65  // Auto Focus delegate
66  useAutoFocusDelegate = new UseAutoFocusDelegate(filterView);
67  filterView->setItemDelegateForColumn(7, useAutoFocusDelegate);
68 
69  // Set Delegates
70  lockDelegate = new LockDelegate(m_currentFilterLabels, filterView);
71  filterView->setItemDelegateForColumn(8, lockDelegate);
72 
73  // Absolute Focus Position
74  filterView->setItemDelegateForColumn(9, noEditDelegate);
75 
76  connect(filterModel, &QSqlTableModel::dataChanged, [this](const QModelIndex & topLeft, const QModelIndex &,
77  const QVector<int> &)
78  {
79  reloadFilters();
80  if (topLeft.column() == 5)
81  emit exposureChanged(filterModel->data(topLeft).toDouble());
82  });
83 }
84 
85 void FilterManager::refreshFilterModel()
86 {
87  if (m_FilterWheel == nullptr || m_currentFilterLabels.empty())
88  return;
89 
90  QString vendor(m_FilterWheel->getDeviceName());
91 
92  //QSqlDatabase::removeDatabase("filter_db");
93  //QSqlDatabase userdb = QSqlDatabase::cloneDatabase(KStarsData::Instance()->userdb()->GetDatabase(), "filter_db");
94  //userdb.open();
95 
96  //delete (filterModel);
97 
98  //filterModel = new QSqlTableModel(this, userdb);
99  if (!filterModel)
100  {
101  QSqlDatabase userdb = QSqlDatabase::cloneDatabase(KStarsData::Instance()->userdb()->GetDatabase(), "filter_db");
102  userdb.open();
103  filterModel = new QSqlTableModel(this, userdb);
104  filterView->setModel(filterModel);
105  }
106  filterModel->setTable("filter");
107  filterModel->setFilter(QString("vendor='%1'").arg(vendor));
108  filterModel->select();
109  filterModel->setEditStrategy(QSqlTableModel::OnFieldChange);
110 
111  // If we have an existing table but it doesn't match the number of current filters
112  // then we remove it.
113  if (filterModel->rowCount() > 0 && filterModel->rowCount() != m_currentFilterLabels.count())
114  {
115  for (int i = 0; i < filterModel->rowCount(); i++)
116  filterModel->removeRow(i);
117 
118  filterModel->select();
119  }
120 
121  // If it is first time, let's populate data
122  if (filterModel->rowCount() == 0)
123  {
124  for (QString &filter : m_currentFilterLabels)
125  KStarsData::Instance()->userdb()->AddFilter(vendor, "", "", filter, 0, 1.0, false, "--", 0);
126 
127  filterModel->select();
128  // Seems ->select() is not enough, have to create a new model.
129  /*delete (filterModel);
130  filterModel = new QSqlTableModel(this, userdb);
131  filterModel->setTable("filter");
132  filterModel->setFilter(QString("vendor='%1'").arg(m_currentFilterDevice->getDeviceName()));
133  filterModel->select();
134  filterModel->setEditStrategy(QSqlTableModel::OnManualSubmit);*/
135  }
136  // Make sure all the filter colors match DB. If not update model to sync with INDI filter values
137  else
138  {
139  for (int i = 0; i < filterModel->rowCount(); ++i)
140  {
141  QModelIndex index = filterModel->index(i, 4);
142  if (filterModel->data(index).toString() != m_currentFilterLabels[i])
143  {
144  filterModel->setData(index, m_currentFilterLabels[i]);
145  }
146  }
147  }
148 
149  lockDelegate->setCurrentFilterList(m_currentFilterLabels);
150 
151  filterModel->setHeaderData(4, Qt::Horizontal, i18n("Filter"));
152 
153  filterModel->setHeaderData(5, Qt::Horizontal, i18n("Filter exposure time during focus"), Qt::ToolTipRole);
154  filterModel->setHeaderData(5, Qt::Horizontal, i18n("Exposure"));
155 
156  filterModel->setHeaderData(6, Qt::Horizontal, i18n("Relative offset in steps"), Qt::ToolTipRole);
157  filterModel->setHeaderData(6, Qt::Horizontal, i18n("Offset"));
158 
159  filterModel->setHeaderData(7, Qt::Horizontal, i18n("Start Auto Focus when filter is activated"), Qt::ToolTipRole);
160  filterModel->setHeaderData(7, Qt::Horizontal, i18n("Auto Focus"));
161 
162  filterModel->setHeaderData(8, Qt::Horizontal, i18n("Lock specific filter when running Auto Focus"), Qt::ToolTipRole);
163  filterModel->setHeaderData(8, Qt::Horizontal, i18n("Lock Filter"));
164 
165  filterModel->setHeaderData(9, Qt::Horizontal,
166  i18n("Flat frames are captured at this focus position. It is updated automatically by focus process if enabled."),
168  filterModel->setHeaderData(9, Qt::Horizontal, i18n("Flat Focus Position"));
169 
170  filterView->hideColumn(0);
171  filterView->hideColumn(1);
172  filterView->hideColumn(2);
173  filterView->hideColumn(3);
174 
175  reloadFilters();
176 }
177 
178 void FilterManager::reloadFilters()
179 {
180  qDeleteAll(m_ActiveFilters);
181  currentFilter = nullptr;
182  targetFilter = nullptr;
183  m_ActiveFilters.clear();
184  operationQueue.clear();
185 
186  for (int i = 0; i < filterModel->rowCount(); ++i)
187  {
188  QSqlRecord record = filterModel->record(i);
189  QString id = record.value("id").toString();
190  QString vendor = record.value("Vendor").toString();
191  QString model = record.value("Model").toString();
192  QString type = record.value("Type").toString();
193  QString color = record.value("Color").toString();
194  double exposure = record.value("Exposure").toDouble();
195  int offset = record.value("Offset").toInt();
196  QString lockedFilter = record.value("LockedFilter").toString();
197  bool useAutoFocus = record.value("UseAutoFocus").toInt() == 1;
198  int absFocusPos = record.value("AbsoluteFocusPosition").toInt();
199  OAL::Filter *o = new OAL::Filter(id, model, vendor, type, color, exposure, offset, useAutoFocus, lockedFilter,
200  absFocusPos);
201  m_ActiveFilters.append(o);
202  }
203 }
204 
205 void FilterManager::setCurrentFilterWheel(ISD::FilterWheel *filter)
206 {
207  if (m_FilterWheel == filter)
208  return;
209  else if (m_FilterWheel)
210  m_FilterWheel->disconnect(this);
211 
212  m_FilterWheel = filter;
213 
214  connect(m_FilterWheel, &ISD::ConcreteDevice::textUpdated, this, &FilterManager::processText);
215  connect(m_FilterWheel, &ISD::ConcreteDevice::numberUpdated, this, &FilterManager::processNumber);
216  connect(m_FilterWheel, &ISD::ConcreteDevice::switchUpdated, this, &FilterManager::processSwitch);
217  connect(m_FilterWheel, &ISD::ConcreteDevice::Disconnected, this, [this]()
218  {
219  m_currentFilterLabels.clear();
220  m_currentFilterPosition = -1;
221  //m_currentFilterDevice = nullptr;
222  m_FilterNameProperty = nullptr;
223  m_FilterPositionProperty = nullptr;
224  });
225 
226  m_FilterNameProperty = nullptr;
227  m_FilterPositionProperty = nullptr;
228  m_FilterConfirmSet = nullptr;
229  initFilterProperties();
230 }
231 
232 void FilterManager::initFilterProperties()
233 {
234  if (m_FilterNameProperty && m_FilterPositionProperty)
235  {
236  if (m_FilterConfirmSet == nullptr)
237  m_FilterConfirmSet = m_FilterWheel->getSwitch("CONFIRM_FILTER_SET");
238  return;
239  }
240 
241  filterNameLabel->setText(m_FilterWheel->getDeviceName());
242 
243  m_currentFilterLabels.clear();
244 
245  m_FilterNameProperty = m_FilterWheel->getText("FILTER_NAME");
246  m_FilterPositionProperty = m_FilterWheel->getNumber("FILTER_SLOT");
247  m_FilterConfirmSet = m_FilterWheel->getSwitch("CONFIRM_FILTER_SET");
248 
249  m_currentFilterPosition = getFilterPosition(true);
250  m_currentFilterLabels = getFilterLabels(true);
251 
252  if (m_currentFilterLabels.isEmpty() == false)
253  refreshFilterModel();
254 
255  if (m_currentFilterPosition >= 1 && m_currentFilterPosition <= m_ActiveFilters.count())
256  lastFilterOffset = m_ActiveFilters[m_currentFilterPosition - 1]->offset();
257 }
258 
259 QStringList FilterManager::getFilterLabels(bool forceRefresh)
260 {
261  if (forceRefresh == false || m_FilterNameProperty == nullptr)
262  return m_currentFilterLabels;
263 
264  QStringList filterList;
265 
266  QStringList filterAlias = Options::filterAlias();
267 
268  for (int i = 0; i < m_FilterPositionProperty->np[0].max; i++)
269  {
270  QString item;
271 
272  if (m_FilterNameProperty != nullptr && (i < m_FilterNameProperty->ntp))
273  item = m_FilterNameProperty->tp[i].text;
274  else if (i < filterAlias.count() && filterAlias[i].isEmpty() == false)
275  item = filterAlias.at(i);
276 
277  filterList.append(item);
278  }
279 
280  return filterList;
281 }
282 
283 int FilterManager::getFilterPosition(bool forceRefresh)
284 {
285  if (forceRefresh == false || m_FilterPositionProperty == nullptr)
286  return m_currentFilterPosition;
287 
288  return static_cast<int>(m_FilterPositionProperty->np[0].value);
289 }
290 
291 bool FilterManager::setFilterPosition(uint8_t position, FilterPolicy policy)
292 {
293  // Position 1 to Max
294  if (position > m_ActiveFilters.count())
295  return false;
296 
297  m_Policy = policy;
298  currentFilter = m_ActiveFilters[m_currentFilterPosition - 1];
299  targetFilter = m_ActiveFilters[position - 1];
300 
301  if (currentFilter == targetFilter)
302  {
303  emit ready();
304  return true;
305  }
306 
307  buildOperationQueue(FILTER_CHANGE);
308 
309  executeOperationQueue();
310 
311  return true;
312 }
313 
314 void FilterManager::processNumber(INumberVectorProperty *nvp)
315 {
316  if (nvp->s != IPS_OK || strcmp(nvp->name, "FILTER_SLOT") || m_FilterWheel == nullptr
317  || (nvp->device != m_FilterWheel->getDeviceName()))
318  return;
319 
320  m_FilterPositionProperty = nvp;
321 
322  if (m_currentFilterPosition != static_cast<int>(m_FilterPositionProperty->np[0].value))
323  {
324  m_currentFilterPosition = static_cast<int>(m_FilterPositionProperty->np[0].value);
325  emit positionChanged(m_currentFilterPosition);
326  }
327 
328  if (state == FILTER_CHANGE)
329  executeOperationQueue();
330  // If filter is changed externally, record its current offset as the starting offset.
331  else if (state == FILTER_IDLE && m_ActiveFilters.count() >= m_currentFilterPosition)
332  lastFilterOffset = m_ActiveFilters[m_currentFilterPosition - 1]->offset();
333 
334  // Check if we have to apply Focus Offset
335  // Focus offsets are always applied first
336 
337 
338 
339  // Check if we have to start Auto Focus
340  // If new filter position changed, and new filter policy is to perform auto-focus then autofocus is initiated.
341 
342  // Capture Module
343  // 3x L ---> 3x HA ---> 3x L
344  // Capture calls setFilterPosition("L").
345  // 0. Change filter to desired filter "L"
346  // 1. Is there any offset from last offset that needs to be applied?
347  // 1.1 Yes --> Apply focus offset and wait until position is changed:
348  // 1.1.1 Position complete, now check for useAutoFocus policy (#2).
349  // 1.1.2 Position failed, retry?
350  // 1.2 No --> Go to #2
351  // 2. Is there autofocus policy for current filter?
352  // 2.1. Yes --> Check filter lock policy
353  // 2.1.1 If filter lock is another filter --> Change filter
354  // 2.1.2 If filter lock is same filter --> proceed to 2.3
355  // 2.2 No --> Process to 2.3
356  // 2.3 filter lock policy filter is applied, start autofocus.
357  // 2.4 Autofocus complete. Check filter lock policy
358  // 2.4.1 If filter lock policy was applied --> revert filter
359  // 2.4.1.1 If filter offset policy is applicable --> Apply offset
360  // 2.4.1.2 If no filter offset policy is applicable --> Go to 2.5
361  // 2.4.2 No filter lock policy, go to 2.5
362  // 2.5 All complete, emit ready()
363 
364  // Example. Current filter L. setFilterPosition("HA"). AutoFocus = YES. HA lock policy: L, HA offset policy: +100 with respect to L
365  // Operation Stack. offsetDiff = 100
366  // If AutoFocus && current filter = lock policy filter
367  // AUTO_FOCUS (on L)
368  // CHANGE_FILTER (to HA)
369  // APPLY_OFFSET: +100
370 
371  // Example. Current filter L. setFilterPosition("HA"). AutoFocus = No. HA lock policy: L, HA offset policy: +100 with respect to L
372  // Operation Stack. offsetDiff = 100
373  // CHANGE_FILTER (to HA)
374  // APPLY_OFFSET: +100
375 
376 
377 
378 
379  // Example. Current filter R. setFilterPosition("B"). AutoFocus = YES. B lock policy: "--", B offset policy: +70 with respect to L
380  // R offset = -50 with respect to L
381  // FILTER_CHANGE (to B)
382  // FILTER_OFFSET (+120)
383  // AUTO_FOCUS
384 
385  // Example. Current filter R. setFilterPosition("HA"). AutoFocus = YES. HA lock policy: L, HA offset policy: +100 with respect to L
386  // R offset = -50 with respect to L
387  // Operation Stack. offsetDiff = +150
388  // CHANGE_FILTER (to L)
389  // APPLY_OFFSET: +50 (L - R)
390  // AUTO_FOCUS
391  // CHANGE_FILTER (HA)
392  // APPLY_OFFSET: +100
393 
394 
395 
396  // Example. Current filter R. setFilterPosition("HA"). AutoFocus = No. HA lock policy: L, HA offset policy: +100 with respect to L
397  // R offset = -50 with respect to L
398  // Operation Stack. offsetDiff = +150
399  // CHANGE_FILTER (to HA)
400  // APPLY_OFFSET: +150 (HA - R)
401 
402 
403 
404  // Example. Current filter L. setFilterPosition("R"). AutoFocus = Yes. R lock policy: R, R offset policy: -50 with respect to L
405  // Operation Stack. offsetDiff = -50
406  // CHANGE_FILTER (to R)
407  // APPLY_OFFSET: -50 (R - L)
408  // AUTO_FOCUS
409 
410 
411 }
412 
413 void FilterManager::processText(ITextVectorProperty *tvp)
414 {
415  if (strcmp(tvp->name, "FILTER_NAME") || m_FilterWheel == nullptr
416  || (tvp->device != m_FilterWheel->getDeviceName()) )
417  return;
418 
419  m_FilterNameProperty = tvp;
420 
421  QStringList newFilterLabels = getFilterLabels(true);
422 
423  if (newFilterLabels != m_currentFilterLabels)
424  {
425  m_currentFilterLabels = newFilterLabels;
426 
427  refreshFilterModel();
428 
429  emit labelsChanged(newFilterLabels);
430  }
431 }
432 
433 void FilterManager::processSwitch(ISwitchVectorProperty *svp)
434 {
435  if (m_FilterWheel == nullptr || (svp->device != m_FilterWheel->getDeviceName()))
436  return;
437 
438 }
439 
440 void FilterManager::buildOperationQueue(FilterState operation)
441 {
442  operationQueue.clear();
443  m_useTargetFilter = false;
444 
445  switch (operation)
446  {
447  case FILTER_CHANGE:
448  {
449  if ( (m_Policy & CHANGE_POLICY) && targetFilter != currentFilter)
450  m_useTargetFilter = true;
451 
452  if (m_useTargetFilter)
453  {
454  operationQueue.enqueue(FILTER_CHANGE);
455  if (m_FocusReady && (m_Policy & OFFSET_POLICY))
456  operationQueue.enqueue(FILTER_OFFSET);
457  }
458 
459  if (m_FocusReady && (m_Policy & AUTOFOCUS_POLICY) && targetFilter->useAutoFocus())
460  operationQueue.enqueue(FILTER_AUTOFOCUS);
461  }
462  break;
463 
464  default:
465  break;
466  }
467 }
468 
469 bool FilterManager::executeOperationQueue()
470 {
471  if (operationQueue.isEmpty())
472  {
473  state = FILTER_IDLE;
474  emit newStatus(state);
475  emit ready();
476  return false;
477  }
478 
479  FilterState nextOperation = operationQueue.dequeue();
480 
481  bool actionRequired = true;
482 
483  switch (nextOperation)
484  {
485  case FILTER_CHANGE:
486  {
487  if (m_ConfirmationPending)
488  return true;
489 
490  state = FILTER_CHANGE;
491  if (m_useTargetFilter)
492  targetFilterPosition = m_ActiveFilters.indexOf(targetFilter) + 1;
493  m_FilterWheel->setPosition(targetFilterPosition);
494  emit newStatus(state);
495 
496  if (m_FilterConfirmSet)
497  {
498  connect(KSMessageBox::Instance(), &KSMessageBox::accepted, this, [this]()
499  {
500  KSMessageBox::Instance()->disconnect(this);
501  m_ConfirmationPending = false;
502  m_FilterWheel->confirmFilter();
503  });
504  connect(KSMessageBox::Instance(), &KSMessageBox::rejected, this, [this]()
505  {
506  KSMessageBox::Instance()->disconnect(this);
507  m_ConfirmationPending = false;
508  });
509 
510  m_ConfirmationPending = true;
511 
512  KSMessageBox::Instance()->questionYesNo(i18n("Set filter to %1. Is filter set?", targetFilter->color()),
513  i18n("Confirm Filter"));
514  }
515  }
516  break;
517 
518  case FILTER_OFFSET:
519  {
520  state = FILTER_OFFSET;
521  if (m_useTargetFilter)
522  {
523  targetFilterOffset = targetFilter->offset() - lastFilterOffset;
524  lastFilterOffset = targetFilter->offset();
525  currentFilter = targetFilter;
526  m_useTargetFilter = false;
527  }
528  if (targetFilterOffset == 0)
529  actionRequired = false;
530  else
531  {
532  emit newFocusOffset(targetFilterOffset, false);
533  emit newStatus(state);
534  }
535  }
536  break;
537 
538  case FILTER_AUTOFOCUS:
539  state = FILTER_AUTOFOCUS;
540  qCDebug(KSTARS) << "FilterManager.cpp is triggering autofocus.";
541  emit newStatus(state);
542  emit checkFocus(0.01);
543  break;
544 
545  default:
546  break;
547  }
548 
549  // If an additional action is required, return return and continue later
550  if (actionRequired)
551  return true;
552  // Otherwise, continue processing the queue
553  else
554  return executeOperationQueue();
555 }
556 
557 bool FilterManager::executeOneOperation(FilterState operation)
558 {
559  bool actionRequired = false;
560 
561  switch (operation)
562  {
563  default:
564  break;
565  }
566 
567  return actionRequired;
568 }
569 
570 void FilterManager::setFocusOffsetComplete()
571 {
572  if (state == FILTER_OFFSET)
573  executeOperationQueue();
574 }
575 
576 double FilterManager::getFilterExposure(const QString &name) const
577 {
578  if (m_currentFilterLabels.empty() ||
579  m_currentFilterPosition < 1 ||
580  m_currentFilterPosition > m_currentFilterLabels.count())
581  return 1;
582 
583  QString color = name;
584  if (color.isEmpty())
585  color = m_currentFilterLabels[m_currentFilterPosition - 1];
586  // Search for locked filter by filter color name
587  auto pos = std::find_if(m_ActiveFilters.begin(), m_ActiveFilters.end(), [color](OAL::Filter * oneFilter)
588  {
589  return (oneFilter->color() == color);
590  });
591 
592  if (pos != m_ActiveFilters.end())
593  return (*pos)->exposure();
594 
595  // Default value
596  return 1;
597 }
598 
599 bool FilterManager::setFilterExposure(int index, double exposure)
600 {
601  if (m_currentFilterLabels.empty())
602  return false;
603 
604  QString color = m_currentFilterLabels[index];
605  for (int i = 0; i < m_ActiveFilters.count(); i++)
606  {
607  if (color == m_ActiveFilters[i]->color())
608  {
609  filterModel->setData(filterModel->index(i, 5), exposure);
610  filterModel->submitAll();
611  refreshFilterModel();
612  return true;
613  }
614  }
615 
616  return false;
617 }
618 
619 bool FilterManager::setFilterAbsoluteFocusPosition(int index, int absFocusPos)
620 {
621  if (index < 0 || index >= m_currentFilterLabels.count())
622  return false;
623 
624  QString color = m_currentFilterLabels[index];
625  for (int i = 0; i < m_ActiveFilters.count(); i++)
626  {
627  if (color == m_ActiveFilters[i]->color())
628  {
629  filterModel->setData(filterModel->index(i, 9), absFocusPos);
630  filterModel->submitAll();
631  refreshFilterModel();
632  return true;
633  }
634  }
635 
636  return false;
637 }
638 
639 QString FilterManager::getFilterLock(const QString &name) const
640 {
641  // Search for locked filter by filter color name
642  auto pos = std::find_if(m_ActiveFilters.begin(), m_ActiveFilters.end(), [name](OAL::Filter * oneFilter)
643  {
644  return (oneFilter->color() == name);
645  });
646 
647  if (pos != m_ActiveFilters.end())
648  return (*pos)->lockedFilter();
649 
650  // Default value
651  return "--";
652 }
653 
654 bool FilterManager::setFilterLock(int index, QString name)
655 {
656  if (m_currentFilterLabels.empty())
657  return false;
658 
659  QString color = m_currentFilterLabels[index];
660  for (int i = 0; i < m_ActiveFilters.count(); i++)
661  {
662  if (color == m_ActiveFilters[i]->color())
663  {
664  filterModel->setData(filterModel->index(i, 8), name);
665  filterModel->submitAll();
666  refreshFilterModel();
667  return true;
668  }
669  }
670 
671  return false;
672 }
673 
674 void FilterManager::removeDevice(ISD::GenericDevice *device)
675 {
676  if (m_FilterWheel && (m_FilterWheel->getDeviceName() == device->getDeviceName()))
677  {
678  m_FilterNameProperty = nullptr;
679  m_FilterPositionProperty = nullptr;
680  m_FilterWheel = nullptr;
681  m_currentFilterLabels.clear();
682  m_currentFilterPosition = 0;
683  qDeleteAll(m_ActiveFilters);
684  m_ActiveFilters.clear();
685  delete(filterModel);
686  filterModel = nullptr;
687  }
688 }
689 
690 void FilterManager::setFocusStatus(Ekos::FocusState focusState)
691 {
692  if (state == FILTER_AUTOFOCUS)
693  {
694  switch (focusState)
695  {
696  case FOCUS_COMPLETE:
697  executeOperationQueue();
698  break;
699 
700  case FOCUS_FAILED:
701  if (++retries == 3)
702  {
703  retries = 0;
704  emit failed();
705  return;
706  }
707  // Restart again
708  emit checkFocus(0.01);
709  break;
710 
711  default:
712  break;
713 
714  }
715  }
716 }
717 
718 bool FilterManager::syncAbsoluteFocusPosition(int index)
719 {
720  if (index < 0 || index > m_ActiveFilters.count())
721  {
722  qCWarning(KSTARS_INDI) << __FUNCTION__ << "index" << index << "is out of bounds.";
723  return false;
724  }
725 
726  int absFocusPos = m_ActiveFilters[index]->absoluteFocusPosition();
727 
728  if (m_FocusAbsPosition == absFocusPos)
729  {
730  m_FocusAbsPositionPending = false;
731  return true;
732  }
733  else if (m_FocusAbsPositionPending == false)
734  {
735  m_FocusAbsPositionPending = true;
736  emit newFocusOffset(absFocusPos, true);
737  }
738 
739  return false;
740 }
741 
742 bool FilterManager::setFilterNames(const QStringList &newLabels)
743 {
744  if (m_FilterWheel == nullptr || m_currentFilterLabels.empty())
745  return false;
746 
747  m_FilterWheel->setLabels(newLabels);
748  return true;
749 }
750 
751 QJsonObject FilterManager::toJSON()
752 {
753  if (!m_FilterWheel)
754  return QJsonObject();
755 
756  QJsonArray filters;
757 
758  for (int i = 0; i < filterModel->rowCount(); ++i)
759  {
760  QJsonObject oneFilter =
761  {
762  {"index", i},
763  {"label", filterModel->data(filterModel->index(i, FM_LABEL)).toString()},
764  {"exposure", filterModel->data(filterModel->index(i, FM_EXPOSURE)).toDouble()},
765  {"offset", filterModel->data(filterModel->index(i, FM_OFFSET)).toInt()},
766  {"autofocus", filterModel->data(filterModel->index(i, FM_AUTO_FOCUS)).toBool()},
767  {"lock", filterModel->data(filterModel->index(i, FM_LOCK_FILTER)).toString()},
768  {"flat", filterModel->data(filterModel->index(i, FM_FLAT_FOCUS)).toInt()},
769  };
770 
771  filters.append(oneFilter);
772  }
773 
774  QJsonObject data =
775  {
776  {"device", m_FilterWheel->getDeviceName()},
777  {"filters", filters}
778  };
779 
780  return data;
781 
782 }
783 
784 void FilterManager::setFilterData(const QJsonObject &settings)
785 {
786  if (!m_FilterWheel)
787  return;
788 
789  if (settings["device"].toString() != m_FilterWheel->getDeviceName())
790  return;
791 
792  QJsonArray filters = settings["filters"].toArray();
793  QStringList labels = getFilterLabels();
794 
795  for (auto oneFilterRef : filters)
796  {
797  QJsonObject oneFilter = oneFilterRef.toObject();
798  int row = oneFilter["index"].toInt();
799 
800  labels[row] = oneFilter["label"].toString();
801  filterModel->setData(filterModel->index(row, FM_LABEL), oneFilter["label"].toString());
802  filterModel->setData(filterModel->index(row, FM_EXPOSURE), oneFilter["exposure"].toDouble());
803  filterModel->setData(filterModel->index(row, FM_OFFSET), oneFilter["offset"].toInt());
804  filterModel->setData(filterModel->index(row, FM_AUTO_FOCUS), oneFilter["autofocus"].toBool());
805  filterModel->setData(filterModel->index(row, FM_LOCK_FILTER), oneFilter["lock"].toString());
806  filterModel->setData(filterModel->index(row, FM_FLAT_FOCUS), oneFilter["flat"].toInt());
807  }
808 
809  setFilterNames(labels);
810  filterModel->submitAll();
811  refreshFilterModel();
812 }
813 
814 }
void append(const T &value)
void AddFilter(const QString &vendor, const QString &model, const QString &type, const QString &color, int offset, double exposure, bool useAutoFocus, const QString &lockedFilter, int absFocusPos)
Add a new filter to the database.
Definition: ksuserdb.cpp:1245
ToolTipRole
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Type type(const QSqlDatabase &db)
Ekos is an advanced Astrophotography tool for Linux. It is based on a modular extensible framework to...
Definition: align.cpp:70
int count(const T &value) const const
int column() const const
KSUserDB * userdb()
Definition: kstarsdata.h:214
const QList< QKeySequence > & close()
QVariant value(int index) const const
void toggled(bool checked)
void rejected()
double toDouble(bool *ok) const const
QString i18n(const char *text, const TYPE &arg...)
QSqlDatabase cloneDatabase(const QSqlDatabase &other, const QString &connectionName)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
char * toString(const T &value)
Horizontal
bool isEmpty() const const
const T & at(int i) const const
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
int toInt(bool *ok) const const
This is the main window for KStars. In addition to the GUI elements, the class contains the program c...
Definition: kstars.h:92
QString name(StandardShortcut id)
void append(const QJsonValue &value)
QString toString() const const
void accepted()
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Aug 15 2022 04:04:01 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.