File indexing completed on 2024-04-28 03:43:16

0001 /*
0002     SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "captureprocessoverlay.h"
0008 #include "QTime"
0009 #include "QFileInfo"
0010 
0011 CaptureProcessOverlay::CaptureProcessOverlay(QWidget *parent) : QWidget(parent)
0012 {
0013     setupUi(this);
0014     // use white as text color
0015     setStyleSheet("color: rgb(255, 255, 255);");
0016     connect(updateStatisticsButton, &QPushButton::clicked, [&]
0017     {
0018         m_captureHistory.updateTargetStatistics();
0019         // refresh the display for the current frame
0020         updateFrameData();
0021         // refresh the statistics display
0022         displayTargetStatistics();
0023     });
0024 }
0025 
0026 bool CaptureProcessOverlay::addFrameData(FrameData data)
0027 {
0028     if (m_captureHistory.addFrame(data) == false)
0029         return false;
0030     // refresh the display for the current frame
0031     updateFrameData();
0032     // refresh the statistics display
0033     displayTargetStatistics();
0034     return true;
0035 }
0036 
0037 void CaptureProcessOverlay::updateFrameData()
0038 {
0039     // nothing to display
0040     if (hasFrames() == false)
0041     {
0042         frameDataWidget->setVisible(false);
0043         return;
0044     }
0045     frameDataWidget->setVisible(true);
0046     const FrameData currentFrame = m_captureHistory.currentFrame();
0047     frameTypeLabel->setText(QString("%1 %2").arg(CCDFrameTypeNames[currentFrame.frameType]).arg(currentFrame.filterName));
0048     exposureValue->setText(QString("%1 sec").arg(currentFrame.exptime, 0, 'f',
0049                            currentFrame.exptime < 1 ? 2 : currentFrame.exptime < 5 ? 1 : 0));
0050     binningValue->setText(QString("%1x%2").arg(currentFrame.binning.x()).arg(currentFrame.binning.y()));
0051     filenameValue->setText(currentFrame.filename);
0052     geometryValue->setText(QString("%1px x %2px").arg(currentFrame.width).arg(currentFrame.height));
0053 
0054     bool visible = (currentFrame.gain >= 0);
0055     gainLabel->setVisible(visible);
0056     gainValue->setVisible(visible);
0057     gainValue->setText(QString("%1").arg(currentFrame.gain, 0, 'f', 1));
0058 
0059     visible = (currentFrame.offset >= 0);
0060     offsetLabel->setVisible(visible);
0061     offsetValue->setVisible(visible);
0062     offsetValue->setText(QString("%1").arg(currentFrame.offset, 0, 'f', 1));
0063 
0064     visible = (currentFrame.iso != "");
0065     isoValue->setVisible(visible);
0066     isoValue->setText(QString("ISO %1").arg(currentFrame.iso));
0067 
0068     visible = (currentFrame.targetdrift >= 0);
0069     targetDriftLabel->setVisible(visible);
0070     targetDriftValue->setVisible(visible);
0071     targetDriftValue->setText(QString("%L1\"").arg(currentFrame.targetdrift, 0, 'f', 1));
0072 
0073     // determine file creation date
0074     QFileInfo fileinfo(currentFrame.filename);
0075     const QDateTime lastmodified = fileinfo.lastModified();
0076     captureDate->setText(lastmodified.toString("dd.MM.yyyy hh:mm:ss"));
0077 
0078     // update capture counts
0079     if (m_captureHistory.size() > 0)
0080         historyCountsLabel->setText(QString("(%1/%2)").arg(m_captureHistory.position() + 1).arg(m_captureHistory.size()));
0081     else
0082         historyCountsLabel->setText("");
0083 
0084     // update enabling of the navigation buttons
0085     historyBackwardButton->setEnabled(m_captureHistory.size() > 0 && m_captureHistory.position() > 0);
0086     historyForwardButton->setEnabled(m_captureHistory.size() > 0 && m_captureHistory.size() - m_captureHistory.position() > 1);
0087 }
0088 
0089 void CaptureProcessOverlay::updateTargetDistance(double targetDiff)
0090 {
0091     // since the history is read only, we need to delete the last one and add it again.
0092     FrameData lastFrame = m_captureHistory.getFrame(m_captureHistory.size() - 1);
0093     lastFrame.targetdrift = targetDiff;
0094     m_captureHistory.deleteFrame(m_captureHistory.size() - 1);
0095     m_captureHistory.addFrame(lastFrame);
0096     updateFrameData();
0097 }
0098 
0099 void CaptureProcessOverlay::displayTargetStatistics()
0100 {
0101     QString display = "";
0102     // iterate over all targets
0103     QList<QString> targets = m_captureHistory.statistics.keys();
0104     for (QList<QString>::iterator target_it = targets.begin(); target_it != targets.end(); target_it++)
0105     {
0106         display.append(QString("<p><b><u>%1</u></b><table border=0>").arg(*target_it == "" ? "<it>" + i18n("No target") + "</it>" :
0107                        *target_it));
0108 
0109         // iterate over all types of captured frames
0110         QList<QPair<CCDFrameType, QString>> keys = m_captureHistory.statistics[*target_it].keys();
0111         for (QList<QPair<CCDFrameType, QString>>::iterator key_it = keys.begin(); key_it != keys.end(); key_it++)
0112         {
0113             // add frame type x filter as header
0114             QString frame_type = CCDFrameTypeNames[key_it->first];
0115             QString filter     = key_it->second;
0116 
0117             // add statistics per exposure time
0118             QList<QPair<int, int>*> counts = m_captureHistory.statistics[*target_it].value(*key_it);
0119             for (QList<QPair<int, int>*>::iterator it = counts.begin(); it != counts.end(); it++)
0120             {
0121                 double exptime = (*it)->first / 1000.0;
0122                 QTime total(0, 0, 0, 0);
0123                 total = total.addMSecs(int((*it)->first * (*it)->second));
0124                 display.append(QString("<tr><td><b>%1 %2</b> (%3 x %4 sec):</td><td style=\"text-align: right\">%5</td></tr>")
0125                                .arg(frame_type).arg(filter)
0126                                .arg((*it)->second)
0127                                .arg(exptime, 0, 'f', exptime < 10 ? 2 : 0)
0128                                .arg(total.toString("hh:mm:ss")));
0129             }
0130         }
0131         display.append("</table></p>");
0132     }
0133     // display statistics
0134     captureStatisticsLabel->setText(display);
0135 }
0136 
0137 bool CaptureProcessOverlay::showNextFrame()
0138 {
0139     if (m_captureHistory.forward())
0140     {
0141         updateFrameData();
0142         return true;
0143     }
0144     return false;
0145 }
0146 
0147 bool CaptureProcessOverlay::showPreviousFrame()
0148 {
0149     if (m_captureHistory.backward())
0150     {
0151         updateFrameData();
0152         return true;
0153     }
0154     return false;
0155 }
0156 
0157 bool CaptureProcessOverlay::deleteFrame(int pos)
0158 {
0159     if (m_captureHistory.deleteFrame(pos) == true)
0160     {
0161         // deleting succeeded, update overlay
0162         updateFrameData();
0163         displayTargetStatistics();
0164         return true;
0165     }
0166     return false;
0167 }
0168 
0169 bool CaptureProcessOverlay::CaptureHistory::addFrame(CaptureProcessOverlay::FrameData data)
0170 {
0171     // check if the file already exists in the history
0172     for (QList<FrameData>::iterator it = m_history.begin(); it != m_history.end(); it++)
0173         if (it->filename == data.filename)
0174             // already exists, ignore
0175             return false;
0176     // history is clean, simply append
0177     m_history.append(data);
0178     m_position = m_history.size() - 1;
0179     countNewFrame(data.target, data.frameType, data.filterName, data.exptime);
0180     return true;
0181 }
0182 
0183 bool CaptureProcessOverlay::CaptureHistory::deleteFrame(int pos)
0184 {
0185     if (m_history.size() != 0 && pos < m_history.size())
0186     {
0187         m_history.removeAt(pos);
0188         // adapt the current position if the deleted frame was deleted before it or itself
0189         if (m_position >= pos)
0190             m_position -= 1;
0191         // ensure staying in range
0192         if (m_position < 0 && m_history.size() > 0)
0193             m_position = 0;
0194         else if (m_position >= m_history.size())
0195             m_position = m_history.size() - 1;
0196         // update statistics, since one file is missing
0197         updateTargetStatistics();
0198         return true;
0199     }
0200     else
0201         return false;
0202 }
0203 
0204 void CaptureProcessOverlay::CaptureHistory::reset()
0205 {
0206     m_position = -1;
0207     m_history.clear();
0208 }
0209 
0210 bool CaptureProcessOverlay::CaptureHistory::forward()
0211 {
0212     if (m_position < m_history.size() - 1)
0213     {
0214         m_position++;
0215         return true;
0216     }
0217     else
0218         return false;
0219 }
0220 
0221 bool CaptureProcessOverlay::CaptureHistory::backward()
0222 {
0223     if (m_position > 0)
0224     {
0225         m_position--;
0226         return true;
0227     }
0228     else
0229         return false;
0230 }
0231 
0232 void CaptureProcessOverlay::CaptureHistory::updateTargetStatistics()
0233 {
0234     statistics.clear();
0235     QList<FrameData> new_history;
0236     // iterate over all entries in the history to update the statistics
0237     for (QList<FrameData>::iterator list_it = m_history.begin(); list_it != m_history.end(); list_it++)
0238     {
0239         // if the corresponding file exists, add it to the statistics
0240         if (QFile(list_it->filename).exists())
0241         {
0242             countNewFrame(list_it->target, list_it->frameType, list_it->filterName, list_it->exptime);
0243             new_history.append(*list_it);
0244         }
0245     }
0246     // switch history lists
0247     m_history.clear();
0248     m_history = new_history;
0249 
0250     // check if the position is correct, if not move to the last element
0251     if (m_position >= m_history.size())
0252         m_position = m_history.size() - 1;
0253 }
0254 
0255 void CaptureProcessOverlay::CaptureHistory::countNewFrame(QString target, CCDFrameType frameType, QString filter,
0256         double exptime)
0257 {
0258     // create search key
0259     QPair<CCDFrameType, QString> key(frameType, filter);
0260     // due to the equality problem with double, we use a milliseconds for exposure time
0261     int exptime_r = int(exptime * 1000);
0262     // create new target map if missing
0263     if (statistics.contains(target) == false)
0264         statistics.insert(target, CaptureProcessOverlay::FrameStatistics());
0265     // create new filter list if missing
0266     if (statistics[target].contains(key) == false)
0267         statistics[target].insert(key, QList<QPair<int, int>*>());
0268 
0269     QPair<int, int>* count = nullptr;
0270     QList<QPair<int, int>*> *counts = &statistics[target][key];
0271     for (QList<QPair<int, int>*>::iterator it = counts->begin(); it != counts->end(); it++)
0272     {
0273         // search for matching exposure time
0274         if ((*it)->first == exptime_r)
0275         {
0276             count = *it;
0277             break;
0278         }
0279     }
0280     // nothing found, initialize
0281     if (count == nullptr)
0282     {
0283         count = new QPair<int, int>(exptime_r, 0);
0284         counts->append(count);
0285     }
0286     // increase the counter
0287     count->second = count->second + 1;
0288 }