Kstars
buildfilteroffsets.cpp
18// The idea is to use the utility once in a while to setup the offsets which them enables the user to avoid having
19// to do an autofocus run when swapping filters. The benefit of this might be to avoid focusing on a difficult-to-
20// focus filter but focusing on a lock filter and then using the offset; or just to avoid an Autofocus run when
23// The utility follows the standard Ekos cpp/h/ui file setup. The basic dialog is contained in the .ui file but
24// because the table is constructed from data at runtime some of the GUI is constructed in code in the .cpp.
25// BFO uses the MVC design pattern. The BuildFilterOffset object is a friend of FilterManager because BFO is closely
26// related to FilterManager. This allows several FilterManager methods to be accessed by BFO. In addition, signals
29// On launch, BFO displays a grid containing all the filters in the Filter Settings. Relevant information is copied across
30// to BFO and the filters appear in the same order. The 1st filter is suffiixed with a "*", marking it as the reference
35// The user needs to set the number of Autofocus (AF) runs to perform on each filter. The default is 5, the maximum is 10.
38// The user presses Run and the utility moves to the processing stage. Extra columns are displayed, one for each AF run,
39// as well as average, new offset and save columns. For each filter the number of requested AF runs is performed. The
40// table cell associated with the in-flight AF run is highlighted. As an AF run completes the results are displayed in
43// Normally, if a lock filter is configured for a particular filter, then when focusing, the lock filter is swapped in
44// AF runs, and then the original filter is swapped back into position. For BFO this model is inappropriate. When an
45// AF run is requested on a filter then AF is always run on that filter so the lock filter policy is not honoured when
48// The user can interrupt processing by pressing stop. A confirm dialog then allows the user to stop BFO or resume.
50// BFO can take a while to complete. For example if 5 AF runs are requested on 8 filters and AF takes, say 2 mins per
51// run, then BFO will take over an hour. During this time environmental conditions such as temperature and altitude
52// could change the focus point. For this reaons, it it possible Adapt each focus run back to the temp and alt applicable
53// during the first AF run for more accurate calculation of the offsets. If Adapt Focus is checked, then the adapted
54// vales are used in calculations; if not checked then the raw (unadapted) values are used. The toggle can be used at
55// any time. The tooltip on each AF run provides a tabular explanation of the adaptations and how the raw value is
56// changed to the adapted value. In order to use Adapt Focus, the ticks per temperature and ticks per altitude fields
57// in the Fillter Settings popup need to be filled in appropriately for each filter being processed.
61// When processing completes the user can review the results. Each processed filter's new offset has an associated save
62// checkbox allowing all or some values to be saved. Saving persists the new offset values in the Filter Settings popup
65// The average AF value for a filter is a simple mean. There are typically not enough sample points taken for robust
66// statistical processing to add any value. So the user needs to review the AF values and decide if they want to remove
67// any outliers (set the AF value to 0 to exclude from processing, or adjust the number). In addition, it is possible
98 connect(this, &BuildFilterOffsets::runAutoFocus, m_filterManager.get(), &FilterManager::signalRunAutoFocus);
99 connect(this, &BuildFilterOffsets::abortAutoFocus, m_filterManager.get(), &FilterManager::signalAbortAutoFocus);
102 connect(m_filterManager.get(), &FilterManager::autoFocusDone, this, &BuildFilterOffsets::autoFocusComplete);
103 connect(m_filterManager.get(), &FilterManager::ready, this, &BuildFilterOffsets::buildTheOffsetsTaskComplete);
106 connect(this, &BuildFilterOffsets::ready, this, &BuildFilterOffsets::buildTheOffsetsTaskComplete);
128 connect(buildOffsetsButtonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, [this]()
130 // Close the dialog down unless lots of processing has been done. In that case put up an "are you sure" popup
150 connect(buildOffsetsTableView, &QAbstractItemView::doubleClicked, this, &BuildFilterOffsets::refChanged);
177 QStringList Headers { i18n("Filter"), i18n("Offset"), i18n("Lock Filter"), i18n("# Focus Runs") };
185 m_BFOModel.setHeaderData(getColumn(BFO_NUM_FOCUS_RUNS), Qt::Horizontal, i18n("# Focus Runs. Set per filter. 0 to ignore"),
220 QStandardItem* item1 = new QStandardItem(QString::number(m_filterManager->m_ActiveFilters[row]->offset()));
224 QStandardItem* item2 = new QStandardItem(m_filterManager->m_ActiveFilters[row]->lockedFilter());
325 i18n("AF Run %1. Calculated automatically but can be edited. Set to 0 to exclude from average.", col + 1),
333 m_BFOModel.setHeaderData(origCols + maxAFRuns, Qt::Horizontal, i18n("AF Average (mean)."), Qt::ToolTipRole);
438 const int height = buildOffsetsTableView->verticalHeader()->length() + buildOffsetsButtonBox->height() +
472 buildOffsetsStatusBar->showMessage(i18n("Problem changing filter to %1...", currentItem.color));
481 buildOffsetsStatusBar->showMessage(i18n("Running Autofocus on %1 (%2/%3)...", currentItem.color, run, numRuns));
487void BuildFilterOffsets::autoFocusComplete(FocusState completionState, int position, double temperature, double altitude)
537void BuildFilterOffsets::processAFcomplete(const int position, const double temperature, const double altitude)
579 solution.deltaTicksTotal = static_cast<int>(round(solution.deltaTicksTemperature + solution.deltaTicksAltitude));
587// Load the focus position depending on the setting of the adaptPos checkbox. The Model update will trigger further updates
611 const QString deltaTemp = i18n("(ΔT=%1)", QString("%1").arg(m_AFSolutions[idx].deltaTemp, 0, 'f', 1));
612 const QString ticksTemp = i18n("(%1 ticks)", QString("%1").arg(m_AFSolutions[idx].deltaTicksTemperature, 0, 'f', 1));
614 const QString deltaAlt = i18n("(ΔAlt=%1)", QString("%1").arg(m_AFSolutions[idx].deltaAlt, 0, 'f', 1));
615 const QString ticksAlt = i18n("(%1 ticks)", QString("%1").arg(m_AFSolutions[idx].deltaTicksAltitude, 0, 'f', 1));
619 i18nc("Graphics tooltip; colume 1 is a header, column 2 is focus position, column 3 is temperature in °C, colunm 4 is altitude in °Alt"
620 "Row 1 is the headers, row 2 is the measured position, row 3 are the adaptations for temperature and altitude, row 4 is adapted position",
625 " caption { text-align: center; vertical-align: top; font-weight: bold; margin: 0px; padding-bottom: 5px;}"
742 if (item->row() == m_refFilter && m_BFOModel.item(item->row(), item->column())->text().toInt() == 0)
746 else if ((item->column() >= getColumn(BFO_AF_RUN_1)) && (item->column() < getColumn(BFO_AVERAGE)))
783// This routine calculates the average of the AF runs. Given that the number of runs is likely to be low
812// calculateOffset updates new offsets when AF averages have been calculated. There are 2 posibilities:
845 const int refFilterAverage = m_BFOModel.item(m_refFilter, getColumn(BFO_AVERAGE))->text().toInt();
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
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)
Cancel
KGuiItem stop()
KGuiItem cancel()
void clicked(bool checked)
void toggled(bool checked)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
void doubleClicked(const QModelIndex &index)
Rejected
virtual void done(int r)
virtual int exec()
ActionRole
ResizeToContents
ClearAndSelect
int column() const const
const QAbstractItemModel * model() const const
int row() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T dequeue()
void enqueue(const T &t)
int column() const const
int row() const const
void setEditable(bool editable)
void setToolTip(const QString &toolTip)
QString text() const const
virtual int columnCount(const QModelIndex &parent) const const override
QStandardItem * item(int row, int column) const const
void itemChanged(QStandardItem *item)
virtual int rowCount(const QModelIndex &parent) const const override
void setColumnCount(int columns)
virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) override
void setHorizontalHeaderItem(int column, QStandardItem *item)
void setHorizontalHeaderLabels(const QStringList &labels)
void setItem(int row, QStandardItem *item)
void setRowCount(int rows)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
int toInt(bool *ok, int base) const const
ToolTipRole
Horizontal
Tool
QFuture< T > run(Function function,...)
void setEnabled(bool)
height
pos
void setupUi(QWidget *widget)
void resize(const QSize &)
void setToolTip(const QString &)
width
void setWindowFlags(Qt::WindowFlags type)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.