146 p.setRenderHint(QPainter::TextAntialiasing,
true);
149 p.fillRect(rect(), QColor(242, 242, 242));
155 if (m_butterflyMode) {
162 QVector<TypeGroup> groups;
163 QMap<QString, int> typeToGroup;
165 const QVector<int> allCh = effectiveChannelIndices();
166 for (
int ch : allCh) {
167 auto info = m_model->channelInfo(ch);
168 if (typeToGroup.contains(info.typeLabel)) {
169 groups[typeToGroup[info.typeLabel]].count++;
171 int idx = groups.size();
172 typeToGroup[info.typeLabel] = idx;
174 g.typeLabel = info.typeLabel;
175 g.color = info.color;
181 int nLanes = groups.size();
185 const int pw = width();
186 const float laneH =
static_cast<float>(height()) / nLanes;
188 QFont nameFont = font();
189 nameFont.setPointSizeF(qBound(8.0,
static_cast<double>(laneH) * 0.25, 13.0));
190 nameFont.setBold(
true);
192 QFont countFont = nameFont;
193 countFont.setPointSizeF(qBound(6.5,
static_cast<double>(laneH) * 0.16, 9.0));
194 countFont.setBold(
false);
196 for (
int i = 0; i < nLanes; ++i) {
197 float yTop = i * laneH;
201 p.setPen(QPen(QColor(200, 200, 200), 1));
202 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
206 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), groups[i].color);
210 p.setPen(QColor(25, 25, 25));
211 QRectF nameRect(kStripWidth + 4, yTop + 1,
212 pw - kStripWidth - 8, laneH * 0.50f);
213 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, groups[i].typeLabel);
216 p.setFont(countFont);
217 p.setPen(QColor(110, 110, 120));
218 QString countStr = QString::number(groups[i].count) + QStringLiteral(
" ch");
219 QRectF countRect(kStripWidth + 4, yTop + laneH * 0.52f,
220 pw - kStripWidth - 8, laneH * 0.30f);
221 p.drawText(countRect, Qt::AlignLeft | Qt::AlignVCenter, countStr);
228 const QVector<int> displayChannels = effectiveChannelIndices();
229 const int totalCh = displayChannels.size();
230 int visibleCount = qMin(m_visibleChannelCount, totalCh - m_firstVisibleChannel);
231 if (visibleCount <= 0)
234 const int pw = width();
235 const float laneH =
static_cast<float>(height()) / visibleCount;
238 const bool dcActive = m_model->removeDC();
241 QFont nameFont = font();
242 nameFont.setPointSizeF(qBound(7.0,
static_cast<double>(laneH) * 0.22, 11.0));
243 nameFont.setBold(
true);
245 QFont typeFont = nameFont;
246 typeFont.setPointSizeF(qBound(6.0,
static_cast<double>(laneH) * 0.15, 8.5));
247 typeFont.setBold(
false);
250 for (
int i = 0; i < visibleCount; ++i) {
251 int logIdx = m_firstVisibleChannel + i;
252 int ch = (logIdx >= 0 && logIdx < displayChannels.size()) ? displayChannels.at(logIdx) : -1;
257 auto info = m_model->channelInfo(ch);
258 float yBot = yTop + laneH;
261 p.setPen(QPen(QColor(200, 200, 200), 1));
263 p.drawLine(QPointF(0, yTop), QPointF(pw, yTop));
267 p.fillRect(QRectF(0, yTop, pw, laneH), QColor(255, 225, 225));
270 p.fillRect(QRectF(0, yTop, kStripWidth, laneH), info.color);
274 QRectF badRect(pw - kBadBadgeW - 2, yTop + 2, kBadBadgeW, kBadBadgeH);
275 p.fillRect(badRect, QColor(210, 30, 30));
276 QFont badFont = typeFont;
277 badFont.setPointSizeF(6.0);
278 badFont.setBold(
true);
281 p.drawText(badRect, Qt::AlignCenter, QStringLiteral(
"BAD"));
286 p.setPen(info.bad ? QColor(180, 20, 20) : QColor(25, 25, 25));
287 int nameBadgeGap = info.bad ? (kBadBadgeW + 4) : 4;
288 QRectF nameRect(kStripWidth + 4, yTop + 1,
289 pw - kStripWidth - nameBadgeGap - 4,
291 QString elidedName = p.fontMetrics().elidedText(
292 info.name, Qt::ElideRight,
static_cast<int>(nameRect.width()));
293 p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName);
296 QString statusLine = info.typeLabel;
298 statusLine += QStringLiteral(
" \u00B7 bad");
299 if (info.isVirtualChannel)
300 statusLine += QStringLiteral(
" \u00B7 deriv");
302 statusLine += QStringLiteral(
" \u00B7 dc");
305 p.setPen(info.bad ? QColor(190, 60, 60) : QColor(110, 110, 120));
306 QRectF statusRect(kStripWidth + 4, yTop + laneH * 0.50f,
307 pw - kStripWidth - 8, laneH * 0.28f);
308 p.drawText(statusRect, Qt::AlignLeft | Qt::AlignVCenter, statusLine);
312 if (m_visSampleFirst < m_visSampleLast)
313 rms = m_model->channelRms(ch, m_visSampleFirst, m_visSampleLast);
314 float level = (info.amplitudeMax > 0.f)
315 ? qBound(0.f, rms / info.amplitudeMax, 1.f)
318 const float barY = yTop + laneH * 0.80f;
319 const float barH = qMax(2.f, laneH * 0.14f);
320 const float barX0 = kStripWidth + 4.f;
321 const float barW = pw - kStripWidth - 8.f;
323 p.fillRect(QRectF(barX0, barY, barW, barH), QColor(215, 215, 215));
328 barColor = QColor(50, 180, 80);
329 else if (level < 0.85f)
330 barColor = QColor(220, 160, 30);
332 barColor = QColor(210, 50, 40);
334 barColor = barColor.darker(115);
335 p.fillRect(QRectF(barX0, barY,
static_cast<qreal
>(barW) * level, barH), barColor);