Kstars

captureprocessoverlay.cpp
1/*
2 SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "captureprocessoverlay.h"
8#include "QTime"
9#include "QFileInfo"
10
11CaptureProcessOverlay::CaptureProcessOverlay(QWidget *parent) : QWidget(parent)
12{
13 setupUi(this);
14 // use white as text color
15 setStyleSheet("color: rgb(255, 255, 255);");
17 {
18 m_captureHistory.updateTargetStatistics();
19 // refresh the display for the current frame
20 updateFrameData();
21 // refresh the statistics display
22 displayTargetStatistics();
23 });
24}
25
26bool CaptureProcessOverlay::addFrameData(FrameData data)
27{
28 if (m_captureHistory.addFrame(data) == false)
29 return false;
30 // refresh the display for the current frame
31 updateFrameData();
32 // refresh the statistics display
33 displayTargetStatistics();
34 return true;
35}
36
37void CaptureProcessOverlay::updateFrameData()
38{
39 // nothing to display
40 if (hasFrames() == false)
41 {
42 frameDataWidget->setVisible(false);
43 return;
44 }
45 frameDataWidget->setVisible(true);
46 const FrameData currentFrame = m_captureHistory.currentFrame();
47 frameTypeLabel->setText(QString("%1 %2").arg(CCDFrameTypeNames[currentFrame.frameType]).arg(currentFrame.filterName));
48 exposureValue->setText(QString("%1 sec").arg(currentFrame.exptime, 0, 'f',
49 currentFrame.exptime < 1 ? 2 : currentFrame.exptime < 5 ? 1 : 0));
50 binningValue->setText(QString("%1x%2").arg(currentFrame.binning.x()).arg(currentFrame.binning.y()));
51 filenameValue->setText(currentFrame.filename);
52 geometryValue->setText(QString("%1px x %2px").arg(currentFrame.width).arg(currentFrame.height));
53
54 bool visible = (currentFrame.gain >= 0);
55 gainLabel->setVisible(visible);
56 gainValue->setVisible(visible);
57 gainValue->setText(QString("%1").arg(currentFrame.gain, 0, 'f', 1));
58
59 visible = (currentFrame.offset >= 0);
60 offsetLabel->setVisible(visible);
61 offsetValue->setVisible(visible);
62 offsetValue->setText(QString("%1").arg(currentFrame.offset, 0, 'f', 1));
63
64 visible = (currentFrame.iso != "");
65 isoValue->setVisible(visible);
66 isoValue->setText(QString("ISO %1").arg(currentFrame.iso));
67
68 visible = (currentFrame.targetdrift >= 0);
69 targetDriftLabel->setVisible(visible);
70 targetDriftValue->setVisible(visible);
71 targetDriftValue->setText(QString("%L1\"").arg(currentFrame.targetdrift, 0, 'f', 1));
72
73 // determine file creation date
74 QFileInfo fileinfo(currentFrame.filename);
75 const QDateTime lastmodified = fileinfo.lastModified();
76 captureDate->setText(lastmodified.toString("dd.MM.yyyy hh:mm:ss"));
77
78 // update capture counts
79 if (m_captureHistory.size() > 0)
80 historyCountsLabel->setText(QString("(%1/%2)").arg(m_captureHistory.position() + 1).arg(m_captureHistory.size()));
81 else
82 historyCountsLabel->setText("");
83
84 // update enabling of the navigation buttons
85 historyBackwardButton->setEnabled(m_captureHistory.size() > 0 && m_captureHistory.position() > 0);
86 historyForwardButton->setEnabled(m_captureHistory.size() > 0 && m_captureHistory.size() - m_captureHistory.position() > 1);
87}
88
89void CaptureProcessOverlay::updateTargetDistance(double targetDiff)
90{
91 // since the history is read only, we need to delete the last one and add it again.
92 FrameData lastFrame = m_captureHistory.getFrame(m_captureHistory.size() - 1);
93 lastFrame.targetdrift = targetDiff;
94 m_captureHistory.deleteFrame(m_captureHistory.size() - 1);
95 m_captureHistory.addFrame(lastFrame);
96 updateFrameData();
97}
98
99void CaptureProcessOverlay::displayTargetStatistics()
100{
101 QString display = "";
102 // iterate over all targets
103 QList<QString> targets = m_captureHistory.statistics.keys();
104 for (QList<QString>::iterator target_it = targets.begin(); target_it != targets.end(); target_it++)
105 {
106 display.append(QString("<p><b><u>%1</u></b><table border=0>").arg(*target_it == "" ? "<it>" + i18n("No target") + "</it>" :
107 *target_it));
108
109 // iterate over all types of captured frames
110 QList<QPair<CCDFrameType, QString>> keys = m_captureHistory.statistics[*target_it].keys();
111 for (QList<QPair<CCDFrameType, QString>>::iterator key_it = keys.begin(); key_it != keys.end(); key_it++)
112 {
113 // add frame type x filter as header
114 QString frame_type = CCDFrameTypeNames[key_it->first];
115 QString filter = key_it->second;
116
117 // add statistics per exposure time
118 QList<QPair<int, int>*> counts = m_captureHistory.statistics[*target_it].value(*key_it);
119 for (QList<QPair<int, int>*>::iterator it = counts.begin(); it != counts.end(); it++)
120 {
121 double exptime = (*it)->first / 1000.0;
122 QTime total(0, 0, 0, 0);
123 total = total.addMSecs(int((*it)->first * (*it)->second));
124 display.append(QString("<tr><td><b>%1 %2</b> (%3 x %4 sec):</td><td style=\"text-align: right\">%5</td></tr>")
125 .arg(frame_type).arg(filter)
126 .arg((*it)->second)
127 .arg(exptime, 0, 'f', exptime < 10 ? 2 : 0)
128 .arg(total.toString("hh:mm:ss")));
129 }
130 }
131 display.append("</table></p>");
132 }
133 // display statistics
134 captureStatisticsLabel->setText(display);
135}
136
137bool CaptureProcessOverlay::showNextFrame()
138{
139 if (m_captureHistory.forward())
140 {
141 updateFrameData();
142 return true;
143 }
144 return false;
145}
146
147bool CaptureProcessOverlay::showPreviousFrame()
148{
149 if (m_captureHistory.backward())
150 {
151 updateFrameData();
152 return true;
153 }
154 return false;
155}
156
157bool CaptureProcessOverlay::deleteFrame(int pos)
158{
159 if (m_captureHistory.deleteFrame(pos) == true)
160 {
161 // deleting succeeded, update overlay
162 updateFrameData();
163 displayTargetStatistics();
164 return true;
165 }
166 return false;
167}
168
169bool CaptureProcessOverlay::CaptureHistory::addFrame(CaptureProcessOverlay::FrameData data)
170{
171 // check if the file already exists in the history
172 for (QList<FrameData>::iterator it = m_history.begin(); it != m_history.end(); it++)
173 if (it->filename == data.filename)
174 // already exists, ignore
175 return false;
176 // history is clean, simply append
177 m_history.append(data);
178 m_position = m_history.size() - 1;
179 countNewFrame(data.target, data.frameType, data.filterName, data.exptime);
180 return true;
181}
182
184{
185 if (m_history.size() != 0 && pos < m_history.size())
186 {
187 m_history.removeAt(pos);
188 // adapt the current position if the deleted frame was deleted before it or itself
189 if (m_position >= pos)
190 m_position -= 1;
191 // ensure staying in range
192 if (m_position < 0 && m_history.size() > 0)
193 m_position = 0;
194 else if (m_position >= m_history.size())
195 m_position = m_history.size() - 1;
196 // update statistics, since one file is missing
197 updateTargetStatistics();
198 return true;
199 }
200 else
201 return false;
202}
203
205{
206 m_position = -1;
207 m_history.clear();
208}
209
211{
212 if (m_position < m_history.size() - 1)
213 {
214 m_position++;
215 return true;
216 }
217 else
218 return false;
219}
220
222{
223 if (m_position > 0)
224 {
225 m_position--;
226 return true;
227 }
228 else
229 return false;
230}
231
233{
234 statistics.clear();
236 // iterate over all entries in the history to update the statistics
237 for (QList<FrameData>::iterator list_it = m_history.begin(); list_it != m_history.end(); list_it++)
238 {
239 // if the corresponding file exists, add it to the statistics
240 if (QFile(list_it->filename).exists())
241 {
242 countNewFrame(list_it->target, list_it->frameType, list_it->filterName, list_it->exptime);
243 new_history.append(*list_it);
244 }
245 }
246 // switch history lists
247 m_history.clear();
248 m_history = new_history;
249
250 // check if the position is correct, if not move to the last element
251 if (m_position >= m_history.size())
252 m_position = m_history.size() - 1;
253}
254
255void CaptureProcessOverlay::CaptureHistory::countNewFrame(QString target, CCDFrameType frameType, QString filter,
256 double exptime)
257{
258 // create search key
259 QPair<CCDFrameType, QString> key(frameType, filter);
260 // due to the equality problem with double, we use a milliseconds for exposure time
261 int exptime_r = int(exptime * 1000);
262 // create new target map if missing
263 if (statistics.contains(target) == false)
264 statistics.insert(target, CaptureProcessOverlay::FrameStatistics());
265 // create new filter list if missing
266 if (statistics[target].contains(key) == false)
267 statistics[target].insert(key, QList<QPair<int, int>*>());
268
269 QPair<int, int>* count = nullptr;
270 QList<QPair<int, int>*> *counts = &statistics[target][key];
271 for (QList<QPair<int, int>*>::iterator it = counts->begin(); it != counts->end(); it++)
272 {
273 // search for matching exposure time
274 if ((*it)->first == exptime_r)
275 {
276 count = *it;
277 break;
278 }
279 }
280 // nothing found, initialize
281 if (count == nullptr)
282 {
283 count = new QPair<int, int>(exptime_r, 0);
284 counts->append(count);
285 }
286 // increase the counter
287 count->second = count->second + 1;
288}
bool deleteFrame(int pos)
Delete the current frame and (if possible) the corresponding file.
bool forward()
Move one step forward in the history.
bool addFrame(FrameData data)
Add a newly captured frame to the history.
int position()
The current navigation position in the capture history.
bool backward()
Move one step backwards in the history.
const FrameData currentFrame()
the currently pointed capture frame
const FrameData getFrame(int pos)
Obtain the frame from the given position in the history.
void updateTargetStatistics()
Iterate over the current target history and add all those where the corresponding file exists.
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
void clicked(bool checked)
bool exists(const QString &fileName)
void append(QList< T > &&value)
iterator begin()
iterator end()
qsizetype size() const const
QList< Key > keys() const const
T value(const Key &key, const T &defaultValue) const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.