169 p.setRenderHint(QPainter::TextAntialiasing,
true);
172 p.fillRect(rect(), QColor(242, 242, 242));
178 if (m_butterflyMode) {
185 QVector<TypeGroup> groups;
186 QMap<QString, int> typeToGroup;
188 const QVector<int> allCh = effectiveChannelIndices();
189 for (
int ch : allCh) {
190 auto info = m_model->channelInfo(ch);
191 if (typeToGroup.contains(info.typeLabel)) {
192 groups[typeToGroup[info.typeLabel]].count++;
194 int idx = groups.size();
195 typeToGroup[info.typeLabel] = idx;
197 g.typeLabel = info.typeLabel;
198 g.color = info.color;
204 int nLanes = groups.size();
208 const int pw = width();
209 const float laneH =
static_cast<float>(height()) / nLanes;
211 QFont nameFont = font();
212 nameFont.setPointSizeF(qBound(8.0,
static_cast<double>(laneH) * 0.25, 13.0));
213 nameFont.setBold(
true);
215 QFont countFont = nameFont;
216 countFont.setPointSizeF(qBound(6.5,
static_cast<double>(laneH) * 0.16, 9.0));
217 countFont.setBold(
false);
219 for (
int i = 0; i < nLanes; ++i) {
220 float yTop = i * laneH;
224 p.setPen(QPen(QColor(200, 200, 200), 1));
225 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
229 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), groups[i].color);
233 p.setPen(QColor(25, 25, 25));
234 QRectF nameRect(kStripWidth + 4, yTop + 1,
235 pw - kStripWidth - 8, laneH * 0.50f);
236 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, groups[i].typeLabel);
239 p.setFont(countFont);
240 p.setPen(QColor(110, 110, 120));
241 QString countStr = QString::number(groups[i].count) + QStringLiteral(
" ch");
242 QRectF countRect(kStripWidth + 4, yTop + laneH * 0.52f,
243 pw - kStripWidth - 8, laneH * 0.30f);
244 p.drawText(countRect, Qt::AlignLeft | Qt::AlignVCenter, countStr);
251 const QVector<int> displayChannels = effectiveChannelIndices();
252 const int totalCh = displayChannels.size();
253 int visibleCount = qMin(m_visibleChannelCount, totalCh - m_firstVisibleChannel);
254 if (visibleCount <= 0)
257 const int pw = width();
258 const float laneH =
static_cast<float>(height()) / visibleCount;
261 const bool dcActive = m_model->removeDC();
264 QFont nameFont = font();
265 nameFont.setPointSizeF(qBound(7.0,
static_cast<double>(laneH) * 0.22, 11.0));
266 nameFont.setBold(
true);
268 QFont typeFont = nameFont;
269 typeFont.setPointSizeF(qBound(6.0,
static_cast<double>(laneH) * 0.15, 8.5));
270 typeFont.setBold(
false);
273 for (
int i = 0; i < visibleCount; ++i) {
274 int logIdx = m_firstVisibleChannel + i;
275 int ch = (logIdx >= 0 && logIdx < displayChannels.size()) ? displayChannels.at(logIdx) : -1;
280 auto info = m_model->channelInfo(ch);
281 float yBot = yTop + laneH;
284 p.setPen(QPen(QColor(200, 200, 200), 1));
286 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
290 p.fillRect(QRectF(0, yTop, pw, laneH), QColor(255, 225, 225));
293 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), info.color);
297 QRectF badRect(pw - kBadBadgeW - 2, yTop + 2, kBadBadgeW, kBadBadgeH);
298 p.fillRect(badRect, QColor(210, 30, 30));
299 QFont badFont = typeFont;
300 badFont.setPointSizeF(6.0);
301 badFont.setBold(
true);
304 p.drawText(badRect, Qt::AlignCenter, QStringLiteral(
"BAD"));
309 p.setPen(info.bad ? QColor(180, 20, 20) : QColor(25, 25, 25));
310 int nameBadgeGap = info.bad ? (kBadBadgeW + 4) : 4;
311 QRectF nameRect(kStripWidth + 4, yTop + 1,
312 pw - kStripWidth - nameBadgeGap - 4,
314 QString elidedName = p.fontMetrics().elidedText(
315 info.name, Qt::ElideRight,
static_cast<int>(nameRect.width()));
316 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName);
319 QString statusLine = info.typeLabel;
321 statusLine += QStringLiteral(
" \u00B7 bad");
322 if (info.isVirtualChannel)
323 statusLine += QStringLiteral(
" \u00B7 deriv");
325 statusLine += QStringLiteral(
" \u00B7 dc");
328 p.setPen(info.bad ? QColor(190, 60, 60) : QColor(110, 110, 120));
329 QRectF statusRect(kStripWidth + 4, yTop + laneH * 0.50f,
330 pw - kStripWidth - 8, laneH * 0.28f);
331 p.drawText(statusRect, Qt::AlignLeft | Qt::AlignVCenter, statusLine);
335 if (m_visSampleFirst < m_visSampleLast)
336 rms = m_model->channelRms(ch, m_visSampleFirst, m_visSampleLast);
337 float level = (info.amplitudeMax > 0.f)
338 ? qBound(0.f, rms / info.amplitudeMax, 1.f)
341 const float barY = yTop + laneH * 0.80f;
342 const float barH = qMax(2.f, laneH * 0.14f);
343 const float barX0 = kStripWidth + 4.f;
344 const float barW = pw - kStripWidth - 8.f;
346 p.fillRect(QRectF(barX0, barY, barW, barH), QColor(215, 215, 215));
351 barColor = QColor(50, 180, 80);
352 else if (level < 0.85f)
353 barColor = QColor(220, 160, 30);
355 barColor = QColor(210, 50, 40);
357 barColor = barColor.darker(115);
358 p.fillRect(QRectF(barX0, barY, barW * level, barH), barColor);