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);");
16 connect(updateStatisticsButton, &QPushButton::clicked, [&]
17 {
18 captureHistory().updateTargetStatistics();
19 // refresh the display for the current frame
20 updateFrameData();
21 // refresh the statistics display
22 displayTargetStatistics();
23 });
24}
25
26void CaptureProcessOverlay::refresh()
27{
28 updateFrameData();
29 // refresh the statistics display
30 displayTargetStatistics();
31}
32
33bool CaptureProcessOverlay::addFrameData(FrameData data, const QString &devicename)
34{
35 if (m_captureHistory[devicename].addFrame(data) == false)
36 return false;
37
38 refresh();
39 return true;
40}
41
42void CaptureProcessOverlay::updateFrameData()
43{
44 // nothing to display
45 if (hasFrames() == false)
46 {
47 frameDataWidget->setVisible(false);
48 return;
49 }
50 frameDataWidget->setVisible(true);
51 const FrameData currentFrame = captureHistory().currentFrame();
52 frameTypeLabel->setText(QString("%1 %2").arg(CCDFrameTypeNames[currentFrame.frameType]).arg(currentFrame.filterName));
53 exposureValue->setText(QString("%1 sec").arg(currentFrame.exptime, 0, 'f',
54 currentFrame.exptime < 1 ? 2 : currentFrame.exptime < 5 ? 1 : 0));
55 binningValue->setText(QString("%1x%2").arg(currentFrame.binning.x()).arg(currentFrame.binning.y()));
56 filenameValue->setText(currentFrame.filename);
57 geometryValue->setText(QString("%1px x %2px").arg(currentFrame.width).arg(currentFrame.height));
58
59 bool visible = (currentFrame.gain >= 0);
60 gainLabel->setVisible(visible);
61 gainValue->setVisible(visible);
62 gainValue->setText(QString("%1").arg(currentFrame.gain, 0, 'f', 1));
63
64 visible = (currentFrame.offset >= 0);
65 offsetLabel->setVisible(visible);
66 offsetValue->setVisible(visible);
67 offsetValue->setText(QString("%1").arg(currentFrame.offset, 0, 'f', 1));
68
69 visible = (currentFrame.iso != "");
70 isoValue->setVisible(visible);
71 isoValue->setText(QString("ISO %1").arg(currentFrame.iso));
72
73 visible = (currentFrame.targetdrift >= 0);
74 targetDriftLabel->setVisible(visible);
75 targetDriftValue->setVisible(visible);
76 targetDriftValue->setText(QString("%L1\"").arg(currentFrame.targetdrift, 0, 'f', 1));
77
78 // determine file creation date
79 QFileInfo fileinfo(currentFrame.filename);
80 const QDateTime lastmodified = fileinfo.lastModified();
81 captureDate->setText(lastmodified.toString("dd.MM.yyyy hh:mm:ss"));
82
83 // update capture counts
84 if (captureHistory().size() > 0)
85 historyCountsLabel->setText(QString("(%1/%2)").arg(captureHistory().position() + 1).arg(captureHistory().size()));
86 else
87 historyCountsLabel->setText("");
88
89 // update enabling of the navigation buttons
90 historyBackwardButton->setEnabled(captureHistory().size() > 0 && captureHistory().position() > 0);
91 historyForwardButton->setEnabled(captureHistory().size() > 0 && captureHistory().size() - captureHistory().position() > 1);
92}
93
94void CaptureProcessOverlay::updateTargetDistance(double targetDiff)
95{
96 // since the history is read only, we need to delete the last one and add it again.
97 FrameData lastFrame = captureHistory().getFrame(captureHistory().size() - 1);
98 lastFrame.targetdrift = targetDiff;
99 captureHistory().deleteFrame(captureHistory().size() - 1);
100 captureHistory().addFrame(lastFrame);
101 updateFrameData();
102}
103
104bool CaptureProcessOverlay::hasFrames()
105{
106 if (m_captureHistory.contains(m_currentCameraDeviceName))
107 return m_captureHistory[m_currentCameraDeviceName].size() > 0;
108
109 return false;
110}
111
112void CaptureProcessOverlay::displayTargetStatistics()
113{
114 QString display = "";
115 // iterate over all targets
116 QList<QString> targets = captureHistory().statistics.keys();
117 for (QList<QString>::iterator target_it = targets.begin(); target_it != targets.end(); target_it++)
118 {
119 display.append(QString("<p><b><u>%1</u></b><table border=0>").arg(*target_it == "" ? "<it>" + i18n("No target") + "</it>" :
120 *target_it));
121
122 // iterate over all types of captured frames
123 QList<QPair<CCDFrameType, QString>> keys = captureHistory().statistics[*target_it].keys();
124 for (QList<QPair<CCDFrameType, QString>>::iterator key_it = keys.begin(); key_it != keys.end(); key_it++)
125 {
126 // add frame type x filter as header
127 QString frame_type = CCDFrameTypeNames[key_it->first];
128 QString filter = key_it->second;
129
130 // add statistics per exposure time
131 QList<QPair<int, int>*> counts = captureHistory().statistics[*target_it].value(*key_it);
132 for (QList<QPair<int, int>*>::iterator it = counts.begin(); it != counts.end(); it++)
133 {
134 double exptime = (*it)->first / 1000.0;
135 QTime total(0, 0, 0, 0);
136 total = total.addMSecs(int((*it)->first * (*it)->second));
137 display.append(QString("<tr><td><b>%1 %2</b> (%3 x %4 sec):</td><td style=\"text-align: right\">%5</td></tr>")
138 .arg(frame_type).arg(filter)
139 .arg((*it)->second)
140 .arg(exptime, 0, 'f', exptime < 10 ? 2 : 0)
141 .arg(total.toString("hh:mm:ss")));
142 }
143 }
144 display.append("</table></p>");
145 }
146 // display statistics
147 captureStatisticsLabel->setText(display);
148}
149
150bool CaptureProcessOverlay::showNextFrame()
151{
152 if (captureHistory().forward())
153 {
154 updateFrameData();
155 return true;
156 }
157 return false;
158}
159
160bool CaptureProcessOverlay::showPreviousFrame()
161{
162 if (captureHistory().backward())
163 {
164 updateFrameData();
165 return true;
166 }
167 return false;
168}
169
170bool CaptureProcessOverlay::deleteFrame(int pos)
171{
172 if (captureHistory().deleteFrame(pos) == true)
173 {
174 // deleting succeeded, update overlay
175 updateFrameData();
176 displayTargetStatistics();
177 return true;
178 }
179 return false;
180}
181
182void CaptureProcessOverlay::setCurrentCameraDeviceName(const QString &devicename)
183{
184 m_currentCameraDeviceName = devicename;
185 refresh();
186}
187
188bool CaptureProcessOverlay::CaptureHistory::addFrame(CaptureProcessOverlay::FrameData data)
189{
190 // check if the file already exists in the history
191 for (QList<FrameData>::iterator it = m_history.begin(); it != m_history.end(); it++)
192 if (it->filename == data.filename)
193 // already exists, ignore
194 return false;
195 // history is clean, simply append
196 m_history.append(data);
197 m_position = m_history.size() - 1;
198 countNewFrame(data.target, data.frameType, data.filterName, data.exptime);
199 return true;
200}
201
203{
204 if (m_history.size() != 0 && pos < m_history.size())
205 {
206 m_history.removeAt(pos);
207 // adapt the current position if the deleted frame was deleted before it or itself
208 if (m_position >= pos)
209 m_position -= 1;
210 // ensure staying in range
211 if (m_position < 0 && m_history.size() > 0)
212 m_position = 0;
213 else if (m_position >= m_history.size())
214 m_position = m_history.size() - 1;
215 // update statistics, since one file is missing
216 updateTargetStatistics();
217 return true;
218 }
219 else
220 return false;
221}
222
224{
225 m_position = -1;
226 m_history.clear();
227}
228
230{
231 if (m_position < m_history.size() - 1)
232 {
233 m_position++;
234 return true;
235 }
236 else
237 return false;
238}
239
241{
242 if (m_position > 0)
243 {
244 m_position--;
245 return true;
246 }
247 else
248 return false;
249}
250
252{
253 statistics.clear();
254 QList<FrameData> new_history;
255 // iterate over all entries in the history to update the statistics
256 for (QList<FrameData>::iterator list_it = m_history.begin(); list_it != m_history.end(); list_it++)
257 {
258 // if the corresponding file exists, add it to the statistics
259 if (QFile(list_it->filename).exists())
260 {
261 countNewFrame(list_it->target, list_it->frameType, list_it->filterName, list_it->exptime);
262 new_history.append(*list_it);
263 }
264 }
265 // switch history lists
266 m_history.clear();
267 m_history = new_history;
268
269 // check if the position is correct, if not move to the last element
270 if (m_position >= m_history.size())
271 m_position = m_history.size() - 1;
272}
273
274void CaptureProcessOverlay::CaptureHistory::countNewFrame(QString target, CCDFrameType frameType, QString filter,
275 double exptime)
276{
277 // create search key
278 QPair<CCDFrameType, QString> key(frameType, filter);
279 // due to the equality problem with double, we use a milliseconds for exposure time
280 int exptime_r = int(exptime * 1000);
281 // create new target map if missing
282 if (statistics.contains(target) == false)
283 statistics.insert(target, CaptureProcessOverlay::FrameStatistics());
284 // create new filter list if missing
285 if (statistics[target].contains(key) == false)
286 statistics[target].insert(key, QList<QPair<int, int>*>());
287
288 QPair<int, int>* count = nullptr;
289 QList<QPair<int, int>*> *counts = &statistics[target][key];
290 for (QList<QPair<int, int>*>::iterator it = counts->begin(); it != counts->end(); it++)
291 {
292 // search for matching exposure time
293 if ((*it)->first == exptime_r)
294 {
295 count = *it;
296 break;
297 }
298 }
299 // nothing found, initialize
300 if (count == nullptr)
301 {
302 count = new QPair<int, int>(exptime_r, 0);
303 counts->append(count);
304 }
305 // increase the counter
306 count->second = count->second + 1;
307}
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.
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)
KGuiItem forward(BidiMode useBidi=IgnoreRTL)
void clicked(bool checked)
QString toString(QStringView format, QCalendar cal) const const
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 Fri Jul 26 2024 11:59:51 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.