diff --git a/src/typeselectorpopup.cpp b/src/typeselectorpopup.cpp index 0ed3d90..620e410 100644 --- a/src/typeselectorpopup.cpp +++ b/src/typeselectorpopup.cpp @@ -97,6 +97,12 @@ public: int h = option.rect.height(); int w = option.rect.width(); + // Scale metrics from font height + QFontMetrics fmMain(m_font); + int iconSz = fmMain.height(); // icon matches text height + int gutterW = fmMain.horizontalAdvance(QChar(0x25B8)) + 4; + int iconColW = iconSz + 4; + // Section: centered dim text with horizontal rules if (isSection) { painter->setPen(t.textDim); @@ -133,18 +139,18 @@ public: if (isCurrent) { painter->setPen(t.text); painter->setFont(m_font); - painter->drawText(QRect(x, y, 10, h), Qt::AlignCenter, + painter->drawText(QRect(x, y, gutterW, h), Qt::AlignCenter, QString(QChar(0x25B8))); } } - x += 10; + x += gutterW; - // Icon 16x16 — only for composite entries + // Icon (scaled to font height) — only for composite entries bool hasIcon = (m_filtered && row >= 0 && row < m_filtered->size() && (*m_filtered)[row].entryKind == TypeEntry::Composite); if (hasIcon) { static QIcon structIcon(QStringLiteral(":/vsicons/symbol-structure.svg")); - QPixmap pm = structIcon.pixmap(16, 16); + QPixmap pm = structIcon.pixmap(iconSz, iconSz); if (isDisabled) { // Paint dimmed QPixmap dimmed(pm.size()); @@ -153,12 +159,12 @@ public: p.setOpacity(0.35); p.drawPixmap(0, 0, pm); p.end(); - painter->drawPixmap(x, y + (h - 16) / 2, dimmed); + painter->drawPixmap(x, y + (h - iconSz) / 2, dimmed); } else { - structIcon.paint(painter, x, y + (h - 16) / 2, 16, 16); + structIcon.paint(painter, x, y + (h - iconSz) / 2, iconSz, iconSz); } } - x += 20; + x += iconColW; // Text QColor textColor; @@ -498,7 +504,9 @@ void TypeSelectorPopup::popup(const QPoint& globalPos) { QString text = t.classKeyword.isEmpty() ? t.displayName : (t.classKeyword + QStringLiteral(" ") + t.displayName); - int w = 10 + 20 + fm.horizontalAdvance(text) + 16; + int gutterW = fm.horizontalAdvance(QChar(0x25B8)) + 4; + int iconColW = fm.height() + 4; + int w = gutterW + iconColW + fm.horizontalAdvance(text) + 16; if (w > maxTextW) maxTextW = w; } int popupW = qBound(280, maxTextW + 24, 500); diff --git a/tests/test_type_selector.cpp b/tests/test_type_selector.cpp index cd92231..ad030f1 100644 --- a/tests/test_type_selector.cpp +++ b/tests/test_type_selector.cpp @@ -793,6 +793,100 @@ private slots: delete splitter; delete doc; } + // ── Test: SVG icon and gutter scale with font size ── + + void testDelegateIconScalesWithFont() { + // Create a popup and set two different font sizes. + // The delegate sizeHint row height should scale with font. + TypeSelectorPopup popup; + + TypeEntry prim; + prim.entryKind = TypeEntry::Primitive; + prim.primitiveKind = NodeKind::Int32; + prim.displayName = QStringLiteral("int32_t"); + + TypeEntry comp; + comp.entryKind = TypeEntry::Composite; + comp.structId = 100; + comp.displayName = QStringLiteral("TestStruct"); + comp.classKeyword = QStringLiteral("struct"); + + // Small font + QFont small(QStringLiteral("Consolas"), 9); + popup.setFont(small); + popup.setTypes({prim, comp}); + popup.popup(QPoint(-9999, -9999)); // offscreen + QApplication::processEvents(); + + auto* listView = popup.findChild(); + QVERIFY(listView); + auto* delegate = listView->itemDelegate(); + QVERIFY(delegate); + + // Find first non-section row for consistent measurement + int dataRow = -1; + for (int i = 0; i < listView->model()->rowCount(); i++) { + QSize h = delegate->sizeHint(QStyleOptionViewItem(), listView->model()->index(i, 0)); + // Non-section rows are taller (font.height + 8 vs + 2) + if (h.height() > QFontMetrics(small).height() + 4) { dataRow = i; break; } + } + QVERIFY2(dataRow >= 0, "Should find a non-section row"); + + QSize smallHint = delegate->sizeHint(QStyleOptionViewItem(), listView->model()->index(dataRow, 0)); + popup.hide(); + + // Large font (simulates zoomed editor) + QFont large(QStringLiteral("Consolas"), 18); + popup.setFont(large); + popup.setTypes({prim, comp}); + popup.popup(QPoint(-9999, -9999)); + QApplication::processEvents(); + + QSize largeHint = delegate->sizeHint(QStyleOptionViewItem(), listView->model()->index(dataRow, 0)); + popup.hide(); + + // Large font should produce taller rows than small font + QVERIFY2(largeHint.height() > smallHint.height(), + qPrintable(QString("Large hint %1 should be > small hint %2") + .arg(largeHint.height()).arg(smallHint.height()))); + + // The ratio should roughly match the font size ratio (18/9 = 2x) + double ratio = double(largeHint.height()) / double(smallHint.height()); + QVERIFY2(ratio > 1.4, qPrintable(QString("Row height ratio %1 should be > 1.4").arg(ratio))); + } + + void testPopupWidthScalesWithFont() { + TypeSelectorPopup popup; + + TypeEntry comp; + comp.entryKind = TypeEntry::Composite; + comp.structId = 100; + comp.displayName = QStringLiteral("MyLongStructName"); + comp.classKeyword = QStringLiteral("struct"); + popup.setTypes({comp}); + + // Small font + QFont small(QStringLiteral("Consolas"), 9); + popup.setFont(small); + popup.popup(QPoint(-9999, -9999)); + QApplication::processEvents(); + int smallW = popup.width(); + popup.hide(); + + // Large font + QFont large(QStringLiteral("Consolas"), 18); + popup.setFont(large); + popup.setTypes({comp}); + popup.popup(QPoint(-9999, -9999)); + QApplication::processEvents(); + int largeW = popup.width(); + popup.hide(); + + // Popup with larger font should be wider + QVERIFY2(largeW > smallW, + qPrintable(QString("Large popup width %1 should be > small %2") + .arg(largeW).arg(smallW))); + } }; QTEST_MAIN(TestTypeSelector)