147 p.setRenderHint(QPainter::TextAntialiasing,
true);
150 p.fillRect(rect(), QColor(242, 242, 242));
156 if (m_butterflyMode) {
164 QVector<TypeGroup> groups;
165 QMap<QString, int> typeToGroup;
167 const QVector<int> allCh = effectiveChannelIndices();
168 for (
int ch : allCh) {
169 auto info = m_model->channelInfo(ch);
170 if (typeToGroup.contains(info.typeLabel)) {
171 groups[typeToGroup[info.typeLabel]].count++;
173 int idx = groups.size();
174 typeToGroup[info.typeLabel] = idx;
176 g.typeLabel = info.typeLabel;
177 g.color = info.color;
183 int nLanes = groups.size();
187 const int pw = width();
188 const float laneH =
static_cast<float>(height()) / nLanes;
190 QFont nameFont = font();
191 nameFont.setPointSizeF(qBound(8.0,
static_cast<double>(laneH) * 0.25, 13.0));
192 nameFont.setBold(
true);
194 QFont countFont = nameFont;
195 countFont.setPointSizeF(qBound(6.5,
static_cast<double>(laneH) * 0.16, 9.0));
196 countFont.setBold(
false);
198 for (
int i = 0; i < nLanes; ++i) {
199 float yTop = i * laneH;
203 p.setPen(QPen(QColor(200, 200, 200), 1));
204 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
208 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), groups[i].color);
212 p.setPen(QColor(25, 25, 25));
213 QRectF nameRect(kStripWidth + 4, yTop + 1,
214 pw - kStripWidth - 8, laneH * 0.50f);
215 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, groups[i].typeLabel);
218 p.setFont(countFont);
219 p.setPen(QColor(110, 110, 120));
220 QString countStr = QString::number(groups[i].count) + QStringLiteral(
" ch");
221 QRectF countRect(kStripWidth + 4, yTop + laneH * 0.52f,
222 pw - kStripWidth - 8, laneH * 0.30f);
223 p.drawText(countRect, Qt::AlignLeft | Qt::AlignVCenter, countStr);
230 const QVector<int> displayChannels = effectiveChannelIndices();
231 const int totalCh = displayChannels.size();
232 int visibleCount = qMin(m_visibleChannelCount, totalCh - m_firstVisibleChannel);
233 if (visibleCount <= 0)
236 const int pw = width();
237 const float laneH =
static_cast<float>(height()) / visibleCount;
240 const bool dcActive = m_model->removeDC();
243 QFont nameFont = font();
244 nameFont.setPointSizeF(qBound(7.0,
static_cast<double>(laneH) * 0.22, 11.0));
245 nameFont.setBold(
true);
247 QFont typeFont = nameFont;
248 typeFont.setPointSizeF(qBound(6.0,
static_cast<double>(laneH) * 0.15, 8.5));
249 typeFont.setBold(
false);
252 for (
int i = 0; i < visibleCount; ++i) {
253 int logIdx = m_firstVisibleChannel + i;
254 int ch = (logIdx >= 0 && logIdx < displayChannels.size()) ? displayChannels.at(logIdx) : -1;
259 auto info = m_model->channelInfo(ch);
260 float yBot = yTop + laneH;
263 p.setPen(QPen(QColor(200, 200, 200), 1));
265 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
269 p.fillRect(QRectF(0, yTop, pw, laneH), QColor(255, 225, 225));
272 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), info.color);
276 QRectF badRect(pw - kBadBadgeW - 2, yTop + 2, kBadBadgeW, kBadBadgeH);
277 p.fillRect(badRect, QColor(210, 30, 30));
278 QFont badFont = typeFont;
279 badFont.setPointSizeF(6.0);
280 badFont.setBold(
true);
283 p.drawText(badRect, Qt::AlignCenter, QStringLiteral(
"BAD"));
288 p.setPen(info.bad ? QColor(180, 20, 20) : QColor(25, 25, 25));
289 int nameBadgeGap = info.bad ? (kBadBadgeW + 4) : 4;
290 QRectF nameRect(kStripWidth + 4, yTop + 1,
291 pw - kStripWidth - nameBadgeGap - 4,
293 QString elidedName = p.fontMetrics().elidedText(
294 info.name, Qt::ElideRight,
static_cast<int>(nameRect.width()));
295 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName);
298 QString statusLine = info.typeLabel;
300 statusLine += QStringLiteral(
" \u00B7 bad");
301 if (info.isVirtualChannel)
302 statusLine += QStringLiteral(
" \u00B7 deriv");
304 statusLine += QStringLiteral(
" \u00B7 dc");
307 p.setPen(info.bad ? QColor(190, 60, 60) : QColor(110, 110, 120));
308 QRectF statusRect(kStripWidth + 4, yTop + laneH * 0.50f,
309 pw - kStripWidth - 8, laneH * 0.28f);
310 p.drawText(statusRect, Qt::AlignLeft | Qt::AlignVCenter, statusLine);
314 if (m_visSampleFirst < m_visSampleLast)
315 rms = m_model->channelRms(ch, m_visSampleFirst, m_visSampleLast);
316 float level = (info.amplitudeMax > 0.f)
317 ? qBound(0.f, rms / info.amplitudeMax, 1.f)
320 const float barY = yTop + laneH * 0.80f;
321 const float barH = qMax(2.f, laneH * 0.14f);
322 const float barX0 = kStripWidth + 4.f;
323 const float barW = pw - kStripWidth - 8.f;
325 p.fillRect(QRectF(barX0, barY, barW, barH), QColor(215, 215, 215));
330 barColor = QColor(50, 180, 80);
331 else if (level < 0.85f)
332 barColor = QColor(220, 160, 30);
334 barColor = QColor(210, 50, 40);
336 barColor = barColor.darker(115);
337 p.fillRect(QRectF(barX0, barY,
static_cast<qreal
>(barW) * level, barH), barColor);