File indexing completed on 2025-04-13 11:19:34
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "probepositioner.h" 0012 #include "oscilloscope.h" 0013 #include "oscilloscopedata.h" 0014 #include "oscilloscopeview.h" 0015 0016 #include <QPaintEvent> 0017 #include <QPainter> 0018 // #include <q3pointarray.h> // 2018.08.14 0019 0020 #include <algorithm> 0021 #include <cmath> 0022 0023 #include <ktechlab_debug.h> 0024 0025 ProbePositioner::ProbePositioner(QWidget *parent) 0026 : QWidget(parent /* , Qt::WNoAutoErase */) 0027 { 0028 m_probePosOffset = 0; 0029 p_draggedProbe = nullptr; 0030 setFixedWidth(int(probeArrowWidth)); 0031 // setBackgroundMode(Qt::NoBackground); // 2018.12.07 0032 setBackgroundRole(QPalette::NoRole); 0033 b_needRedraw = true; 0034 m_pixmap = nullptr; 0035 } 0036 0037 ProbePositioner::~ProbePositioner() 0038 { 0039 delete m_pixmap; 0040 } 0041 0042 void ProbePositioner::forceRepaint() 0043 { 0044 b_needRedraw = true; 0045 repaint(/* false - 2018.12.07 */); 0046 } 0047 0048 int ProbePositioner::probeOutputHeight() const 0049 { 0050 int height = int(Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight); 0051 int numProbes = Oscilloscope::self()->numberOfProbes(); 0052 if (numProbes == 0) 0053 numProbes = 1; 0054 return height / numProbes; 0055 } 0056 0057 int ProbePositioner::probePosition(ProbeData *probeData) const 0058 { 0059 if (!probeData) 0060 return -1; 0061 0062 int spacing = probeOutputHeight(); 0063 int probeNum = Oscilloscope::self()->probeNumber(probeData->id()); 0064 0065 return int(probeArrowHeight / 2 + spacing * (probeNum + probeData->drawPosition())); 0066 } 0067 0068 void ProbePositioner::setProbePosition(ProbeData *probeData, int position) 0069 { 0070 if (!probeData) 0071 return; 0072 0073 int height = int(Oscilloscope::self()->oscilloscopeView->height() - probeArrowHeight); 0074 int numProbes = Oscilloscope::self()->numberOfProbes(); 0075 int spacing = height / numProbes; 0076 int probeNum = Oscilloscope::self()->probeNumber(probeData->id()); 0077 0078 int minPos = int(probeArrowHeight / 2); 0079 int maxPos = int(Oscilloscope::self()->oscilloscopeView->height() - (probeArrowHeight / 2)) - 1; 0080 if (position < minPos) 0081 position = minPos; 0082 else if (position > maxPos) 0083 position = maxPos; 0084 0085 probeData->setDrawPosition(float(position - probeArrowHeight / 2) / float(spacing) - probeNum); 0086 0087 forceRepaint(); 0088 Oscilloscope::self()->oscilloscopeView->updateView(); 0089 } 0090 0091 ProbeData *ProbePositioner::probeAtPosition(const QPoint &pos) 0092 { 0093 int relativeArrowHeight = int(probeArrowHeight * (1. - float(pos.x() / probeArrowWidth))); 0094 0095 const ProbeDataMap::const_iterator end = m_probeDataMap.end(); 0096 for (ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it) { 0097 ProbeData *probeData = it.value(); 0098 int currentPos = probePosition(probeData); 0099 m_probePosOffset = pos.y() - currentPos; 0100 if (std::abs(m_probePosOffset) <= relativeArrowHeight) 0101 return probeData; 0102 } 0103 m_probePosOffset = 0; 0104 return nullptr; 0105 } 0106 0107 void ProbePositioner::slotProbeDataRegistered(int id, ProbeData *probe) 0108 { 0109 m_probeDataMap[id] = probe; 0110 connect(probe, &ProbeData::displayAttributeChanged, this, &ProbePositioner::forceRepaint); 0111 0112 // This connect doesn't really belong here, but it save a lot of code 0113 connect(probe, &ProbeData::displayAttributeChanged, Oscilloscope::self()->oscilloscopeView, &OscilloscopeView::updateView); 0114 forceRepaint(); 0115 Oscilloscope::self()->oscilloscopeView->updateView(); 0116 } 0117 0118 void ProbePositioner::slotProbeDataUnregistered(int id) 0119 { 0120 m_probeDataMap.remove(id); 0121 // We "set" the position of each probe to force it into proper bounds 0122 0123 const ProbeDataMap::const_iterator end = m_probeDataMap.end(); 0124 for (ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it) 0125 setProbePosition(it.value(), probePosition(it.value())); 0126 0127 forceRepaint(); 0128 } 0129 0130 void ProbePositioner::resizeEvent(QResizeEvent *e) 0131 { 0132 delete m_pixmap; 0133 m_pixmap = new QPixmap(e->size()); 0134 QWidget::resizeEvent(e); 0135 forceRepaint(); 0136 } 0137 0138 void ProbePositioner::mousePressEvent(QMouseEvent *e) 0139 { 0140 p_draggedProbe = probeAtPosition(e->pos()); 0141 if (p_draggedProbe) 0142 e->accept(); 0143 else 0144 e->ignore(); 0145 } 0146 0147 void ProbePositioner::mouseReleaseEvent(QMouseEvent *e) 0148 { 0149 if (p_draggedProbe) 0150 e->accept(); 0151 else 0152 e->ignore(); 0153 } 0154 0155 void ProbePositioner::mouseMoveEvent(QMouseEvent *e) 0156 { 0157 if (!p_draggedProbe) { 0158 e->ignore(); 0159 return; 0160 } 0161 e->accept(); 0162 0163 setProbePosition(p_draggedProbe, e->pos().y() - m_probePosOffset); 0164 forceRepaint(); 0165 } 0166 0167 void ProbePositioner::paintEvent(QPaintEvent *e) 0168 { 0169 QRect r = e->rect(); 0170 0171 if (b_needRedraw) { 0172 if (!m_pixmap) { 0173 qCWarning(KTL_LOG) << " unexpected null m_pixmap in " << this; 0174 return; 0175 } 0176 0177 QPainter p; 0178 // m_pixmap->fill( paletteBackgroundColor() ); 0179 m_pixmap->fill(palette().color(backgroundRole())); 0180 const bool startSuccess = p.begin(m_pixmap); 0181 if ((!startSuccess) || (!p.isActive())) { 0182 qCWarning(KTL_LOG) << " painter is not active"; 0183 } 0184 0185 p.setClipRegion(e->region()); 0186 0187 const ProbeDataMap::const_iterator end = m_probeDataMap.end(); 0188 for (ProbeDataMap::const_iterator it = m_probeDataMap.begin(); it != end; ++it) { 0189 ProbeData *probeData = it.value(); 0190 p.setBrush(probeData->color()); 0191 int currentPos = probePosition(probeData); 0192 0193 QPolygon pa(3); 0194 pa[0] = QPoint(0, int(currentPos - (probeArrowHeight / 2))); 0195 pa[1] = QPoint(int(probeArrowWidth), currentPos); 0196 pa[2] = QPoint(0, int(currentPos + (probeArrowHeight / 2))); 0197 0198 p.drawPolygon(pa); 0199 } 0200 b_needRedraw = false; 0201 } 0202 0203 // bitBlt( this, r.x(), r.y(), m_pixmap, r.x(), r.y(), r.width(), r.height() ); // 2018.12.07 0204 QPainter p; 0205 const bool paintStarted = p.begin(this); 0206 if (!paintStarted) { 0207 qCWarning(KTL_LOG) << " failed to start painting "; 0208 } 0209 p.drawImage(r, m_pixmap->toImage(), r); 0210 } 0211 0212 #include "moc_probepositioner.cpp"