File indexing completed on 2024-04-28 03:43:07
0001 /* 0002 SPDX-FileCopyrightText: 2017 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "ui_filtersettings.h" 0010 #include "ekos/ekos.h" 0011 0012 #include <indi/indifilterwheel.h> 0013 #include <indi/indifocuser.h> 0014 #include <oal/filter.h> 0015 0016 #include <QQueue> 0017 #include <QPointer> 0018 #include <QStandardItemModel> 0019 0020 class QSqlTableModel; 0021 class ComboDelegate; 0022 class NotEditableDelegate; 0023 class NotEditableDelegate2dp; 0024 class DoubleDelegate; 0025 class IntegerDelegate; 0026 class ToggleDelegate; 0027 0028 namespace Ekos 0029 { 0030 0031 class FilterManager : public QDialog, public Ui::FilterSettings 0032 { 0033 Q_OBJECT 0034 0035 // BuildFilterOffsets is a friend class so it can access methods in FilterManager 0036 friend class BuildFilterOffsets; 0037 0038 public: 0039 0040 typedef enum 0041 { 0042 CHANGE_POLICY = 1 << 0, 0043 OFFSET_POLICY = 1 << 1, 0044 AUTOFOCUS_POLICY = 1 << 2, 0045 ALL_POLICIES = CHANGE_POLICY | OFFSET_POLICY | AUTOFOCUS_POLICY, 0046 NO_AUTOFOCUS_POLICY = CHANGE_POLICY | OFFSET_POLICY 0047 } FilterPolicy; 0048 0049 enum 0050 { 0051 FM_LABEL = 4, 0052 FM_EXPOSURE, 0053 FM_OFFSET, 0054 FM_AUTO_FOCUS, 0055 FM_LOCK_FILTER, 0056 FM_LAST_AF_SOLUTION, 0057 FM_LAST_AF_TEMP, 0058 FM_LAST_AF_ALT, 0059 FM_TICKS_PER_TEMP, 0060 FM_TICKS_PER_ALT, 0061 FM_WAVELENGTH 0062 }; 0063 0064 FilterManager(QWidget *parent = nullptr); 0065 0066 QJsonObject toJSON(); 0067 void setFilterData(const QJsonObject &settings); 0068 0069 void createFilterModel(); 0070 void refreshFilterModel(); 0071 0072 QStringList getFilterLabels(bool forceRefresh = false); 0073 int getFilterPosition(bool forceRefresh = false); 0074 /** 0075 * @brief refreshFilterLabels Update the filter labels from the device and signal changes. 0076 */ 0077 void refreshFilterLabels(); 0078 /** 0079 * @brief refreshFilterPos Update the filter wheel position and signal changes. 0080 */ 0081 void refreshFilterPosition(); 0082 0083 // The target position and offset 0084 int getTargetFilterPosition() 0085 { 0086 return targetFilterPosition; 0087 } 0088 int getTargetFilterOffset() 0089 { 0090 return targetFilterOffset; 0091 } 0092 0093 /** 0094 * @brief setFilterAbsoluteFocusDetails set params from successful autofocus run 0095 * @param index filter index 0096 * @param focusPos the position of the focus solution 0097 * @param focusTemp the temperature at the time of the focus run 0098 * @param focusAlt the altitude at the time of the focus run 0099 * @return whether function worked or not 0100 */ 0101 bool setFilterAbsoluteFocusDetails(int index, int focusPos, double focusTemp, double focusAlt); 0102 0103 /** 0104 * @brief getFilterAbsoluteFocusDetails get params from the last successful autofocus run 0105 * @param name filter name 0106 * @param focusPos the position of the focus solution 0107 * @param focusTemp the temperature at the time of the focus run 0108 * @param focusAlt the altitude at the time of the focus run 0109 * @return whether function worked or not 0110 */ 0111 bool getFilterAbsoluteFocusDetails(const QString &name, int &focusPos, double &focusTemp, double &focusAlt) const; 0112 0113 // Set absolute focus position, if supported, to the current filter absolute focus position. 0114 bool syncAbsoluteFocusPosition(int index); 0115 0116 /** 0117 * @brief getFilterExposure Get optimal exposure time for the specified filter 0118 * @param name filter to obtain exposure time for 0119 * @return exposure time in seconds. 0120 */ 0121 double getFilterExposure(const QString &name = QString()) const; 0122 bool setFilterExposure(int index, double exposure); 0123 0124 /** 0125 * @brief getFilterOffset returns the offset for the specified filter 0126 * @param name of the filter 0127 * @return filter offset (INVALID_VALUE in the case of a problem) 0128 */ 0129 int getFilterOffset(const QString &name) const; 0130 0131 /** 0132 * @brief setFilterOffset set the offset for the specified filter 0133 * @param color of the filter 0134 * @param the new filter offset 0135 * @return whether or not the operation was successful 0136 */ 0137 bool setFilterOffset(QString color, int offset); 0138 0139 /** 0140 * @brief getFilterWavelength Get mid-point wavelength for the specified filter 0141 * @param name filter to obtain exposure time for 0142 * @return wavelength in nm. 0143 */ 0144 int getFilterWavelength(const QString &name = QString()) const; 0145 0146 /** 0147 * @brief getFilterTicksPerTemp gets the ticks per degree C 0148 * @param name filter to obtain exposure time for 0149 * @return ticks / degree C 0150 */ 0151 double getFilterTicksPerTemp(const QString &name = QString()) const; 0152 0153 /** 0154 * @brief getFilterTicksPerAlt gets the ticks per degree of altitude 0155 * @param name filter to obtain exposure time for 0156 * @return ticks / degree Alt 0157 */ 0158 double getFilterTicksPerAlt(const QString &name = QString()) const; 0159 0160 /** 0161 * @brief getFilterLock Return filter that should be used when running autofocus for the supplied filter 0162 * For example, "Red" filter can be locked to use "Lum" when doing autofocus. "Green" filter can be locked to "--" 0163 * which means that no filter change is necessary. 0164 * @param name filter which we need to query its locked filter. 0165 * @return locked filter. "--" indicates no locked filter and whatever current filter should be used. 0166 * 0167 */ 0168 QString getFilterLock(const QString &name) const; 0169 bool setFilterLock(int index, QString name); 0170 0171 /** 0172 * @brief setCurrentFilterWheel Set the FilterManager active filter wheel. 0173 * @param filter pointer to filter wheel device 0174 */ 0175 void setFilterWheel(ISD::FilterWheel *filter); 0176 ISD::FilterWheel *filterWheel() const 0177 { 0178 return m_FilterWheel; 0179 } 0180 0181 /** 0182 * @brief setFocusReady Set whether a focuser device is active and in use. 0183 * @param enabled true if focus is ready, false otherwise. 0184 */ 0185 void setFocusReady(bool enabled) 0186 { 0187 m_FocusReady = enabled; 0188 } 0189 0190 0191 /** 0192 * @brief applyFilterFocusPolicies Check if we need to apply any filter policies for focus operations. 0193 */ 0194 void applyFilterFocusPolicies(); 0195 0196 /** 0197 * @brief buildFilterOffsets Launch the Build Filter Offsets utility 0198 * @param FM pointer to the FilterManager 0199 */ 0200 void buildFilterOffsets(); 0201 0202 public slots: 0203 // Position. if applyPolicy is true then all filter offsets and autofocus & lock policies are applied. 0204 bool setFilterPosition(uint8_t position, Ekos::FilterManager::FilterPolicy policy = ALL_POLICIES); 0205 // Change filter names 0206 bool setFilterNames(const QStringList &newLabels); 0207 // Offset Request completed 0208 void setFocusOffsetComplete(); 0209 // Remove Device 0210 void removeDevice(const QSharedPointer<ISD::GenericDevice> &device); 0211 // Refresh Filters after model update 0212 void reloadFilters(); 0213 // Resize the dialog to the contents 0214 void resizeDialog(); 0215 // Focus Status 0216 void setFocusStatus(Ekos::FocusState focusState); 0217 // Set absolute focus position 0218 void setFocusAbsolutePosition(int value) 0219 { 0220 m_FocusAbsPosition = value; 0221 } 0222 // Inti filter property after connection 0223 void refreshFilterProperties(); 0224 // Signal from BuildFilterOffsets to run Autofocus. Pass onto Focus 0225 void signalRunAutoFocus(bool buildFilterOffsets); 0226 // Signal from BuildFilterOffsets to abort AF run. Pass onto Focus 0227 void signalAbortAutoFocus(); 0228 // Signal from Focus that Autofocus has completed - used by BuildFilterOffsets utility 0229 void autoFocusComplete(FocusState completionState, int currentPosition, double currentTemperature, double currentAlt); 0230 0231 signals: 0232 // Emitted only when there is a change in the filter slot number 0233 void positionChanged(int); 0234 // Emitted when filter change operation completed successfully including any focus offsets or auto-focus operation 0235 void labelsChanged(QStringList); 0236 // Emitted when filter exposure duration changes 0237 void exposureChanged(double); 0238 // Emitted when filter change completed including all required actions 0239 void ready(); 0240 // Emitted when operation fails 0241 void failed(); 0242 // Status signal 0243 void newStatus(Ekos::FilterState state); 0244 // Run AutoFocus 0245 void runAutoFocus(bool buildOffsets); 0246 // Abort AutoFocus 0247 void abortAutoFocus(); 0248 // New Focus offset requested 0249 void newFocusOffset(int value, bool useAbsoluteOffset); 0250 // database was updated 0251 void updated(); 0252 // Filter ticks per degree of temperature changed 0253 void ticksPerTempChanged(); 0254 // Filter ticks per degree of altitude changed 0255 void ticksPerAltChanged(); 0256 // Filter wavelength changed 0257 void wavelengthChanged(); 0258 // Pass on Autofocus completed signal to Build Filter Offsets 0259 void autoFocusDone(FocusState completionState, int currentPosition, double currentTemperature, double currentAlt); 0260 0261 private slots: 0262 void updateProperty(INDI::Property prop); 0263 void processDisconnect(); 0264 0265 private: 0266 0267 // Filter Wheel Devices 0268 ISD::FilterWheel *m_FilterWheel = { nullptr }; 0269 0270 // Position and Labels 0271 QStringList m_currentFilterLabels; 0272 int m_currentFilterPosition = { -1 }; 0273 double m_currentFilterExposure = { -1 }; 0274 0275 // Filter Structure 0276 QList<OAL::Filter *> m_ActiveFilters; 0277 OAL::Filter *targetFilter = { nullptr }; 0278 OAL::Filter *currentFilter = { nullptr }; 0279 bool m_useTargetFilter = { false }; 0280 0281 // Autofocus retries 0282 uint8_t retries = { 0 }; 0283 0284 int16_t lastFilterOffset { 0 }; 0285 0286 // Table model 0287 QSqlTableModel *m_FilterModel = { nullptr }; 0288 0289 // INDI Properties of current active filter 0290 ITextVectorProperty *m_FilterNameProperty { nullptr }; 0291 INumberVectorProperty *m_FilterPositionProperty { nullptr }; 0292 ISwitchVectorProperty *m_FilterConfirmSet { nullptr }; 0293 0294 // Accessor function to return filter pointer for the passed in name. 0295 // nullptr is returned if there isn't a match 0296 OAL::Filter * getFilterByName(const QString &name) const; 0297 0298 // Operation stack 0299 void buildOperationQueue(FilterState operation); 0300 bool executeOperationQueue(); 0301 bool executeOneOperation(FilterState operation); 0302 0303 // Update model 0304 void syncDBToINDI(); 0305 0306 // Get the list of possible lock filters to set in the combo box. 0307 // The list excludes filters already setup with a lock to prevent nested dependencies 0308 QStringList getLockDelegates(); 0309 0310 // Operation Queue 0311 QQueue<FilterState> operationQueue; 0312 0313 FilterState state = { FILTER_IDLE }; 0314 0315 int targetFilterPosition { -1 }; 0316 int targetFilterOffset { - 1 }; 0317 0318 0319 bool m_FocusReady { false }; 0320 bool m_FocusAbsPositionPending { false}; 0321 int m_FocusAbsPosition { -1 }; 0322 0323 // Delegates 0324 QPointer<ComboDelegate> lockDelegate; 0325 QPointer<NotEditableDelegate> noEditDelegate; 0326 QPointer<DoubleDelegate> exposureDelegate; 0327 QPointer<IntegerDelegate> offsetDelegate; 0328 QPointer<ToggleDelegate> useAutoFocusDelegate; 0329 QPointer<IntegerDelegate> lastAFSolutionDelegate; 0330 QPointer<DoubleDelegate> lastAFTempDelegate; 0331 QPointer<DoubleDelegate> lastAFAltDelegate; 0332 QPointer<DoubleDelegate> ticksPerTempDelegate; 0333 QPointer<DoubleDelegate> ticksPerAltDelegate; 0334 QPointer<IntegerDelegate> wavelengthDelegate; 0335 0336 // Policies 0337 FilterPolicy m_Policy = { ALL_POLICIES }; 0338 0339 bool m_ConfirmationPending { false }; 0340 }; 0341 0342 }