diff --git a/src/ui/SelectionPanel.cpp b/src/ui/SelectionPanel.cpp index aa791d2..4962693 100644 --- a/src/ui/SelectionPanel.cpp +++ b/src/ui/SelectionPanel.cpp @@ -193,6 +193,13 @@ void SelectionPanel::rebuildContent() if (m_content) { m_bodyLayout->addWidget(m_content); + // The show is what makes the card count. A widget created under an + // already-visible parent starts hidden, and a layout treats a hidden item as + // empty -- it adds nothing to the size hint until something shows it, which + // otherwise does not happen until the event loop next runs, long after refit() + // has measured the panel. The panel then fits itself to an empty body and + // collapses to its scroll bar. + m_content->show(); m_content->refresh(); } updateVisibility(); @@ -214,11 +221,6 @@ void SelectionPanel::updateVisibility() void SelectionPanel::refit() { - // The layout drops hidden widgets from its size hint, but only once it has been - // re-run: a card hides and shows its parts as it refreshes, before Qt would get - // around to it on its own. - m_body->layout()->activate(); - const QRect band = m_bandRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx); @@ -234,6 +236,22 @@ void SelectionPanel::refit() return; } + // Measured at the cap rather than at whatever width the panel happens to have. A + // word-wrapped label's size hint follows its current width, so a panel that once + // came out too narrow would keep reporting a narrow, tall hint and stay that way. + m_body->resize(maxWidthPx, m_body->height()); + + // Cards are built and thrown away whole, so the body layout's cached hint describes + // the card before this one until it is discarded. Re-running the layout is what + // makes the current card's parts measurable: a card hides and shows its parts as it + // refreshes, and Qt would not get around to either on its own before the panel is + // sized here. The polish belongs to the same step -- a freshly created chip reports + // an unstyled hint until the stylesheet has reached it, and the chips carry border + // and padding that change their width. + m_body->ensurePolished(); + m_body->layout()->invalidate(); + m_body->layout()->activate(); + int contentWidthPx = qMin(m_body->sizeHint().width(), maxWidthPx); // Word-wrapped labels only know their height once the width is fixed; the layout // reports -1 when nothing in it wraps, in which case the plain hint is exact. diff --git a/src/ui/selection/ItemChipRow.cpp b/src/ui/selection/ItemChipRow.cpp index bccf8a8..7501458 100644 --- a/src/ui/selection/ItemChipRow.cpp +++ b/src/ui/selection/ItemChipRow.cpp @@ -73,6 +73,11 @@ void ItemChipRow::rebuildChips(const std::vector& entries) ItemChip* chip = new ItemChip(icon, this); m_layout->addWidget(chip, static_cast(index) / kChipsPerRow, static_cast(index) % kChipsPerRow); + // Shown right away, because the panel measures itself as soon as this returns. A + // widget created under an already-visible parent starts hidden, and a layout + // treats a hidden item as empty, so an unshown chip would add nothing to the + // size hint and the panel would be fitted to a buffer section that looks empty. + chip->show(); m_chips.push_back(chip); } } diff --git a/src/ui/selection/RecipeSummaryRow.cpp b/src/ui/selection/RecipeSummaryRow.cpp index 37e3369..ecf85b5 100644 --- a/src/ui/selection/RecipeSummaryRow.cpp +++ b/src/ui/selection/RecipeSummaryRow.cpp @@ -13,6 +13,18 @@ namespace // Size the item icons are drawn at on the summary line, in device-independent pixels. const int kSummaryIconSizePx = 14; +// Adds a freshly built label to the summary and shows it. +// +// The show is what makes it count: a widget created under an already-visible parent +// starts hidden, and a layout treats a hidden item as empty, so an unshown label would +// add nothing to the size hint the panel measures itself against as soon as this +// returns. +void addAndShow(QHBoxLayout* layout, QLabel* label) +{ + layout->addWidget(label); + label->show(); +} + } // namespace @@ -71,14 +83,14 @@ void RecipeSummaryRow::rebuild(const std::vector& inputs, if (!inputs.empty()) { const QChar rightArrow(0x2192); // U+2192 RIGHTWARDS ARROW - m_layout->addWidget(new QLabel(QString(rightArrow), this)); + addAndShow(m_layout, new QLabel(QString(rightArrow), this)); } addAmounts(outputs); if (durationSeconds > 0.0) { const QChar middleDot(0x00B7); // U+00B7 MIDDLE DOT - m_layout->addWidget(new QLabel( + addAndShow(m_layout, new QLabel( QStringLiteral("%1 %2").arg(middleDot).arg( tr("%1 s").arg(durationSeconds, 0, 'f', 1)), this)); } @@ -96,13 +108,13 @@ void RecipeSummaryRow::addAmounts(const std::vector& amounts) QLabel* iconLabel = new QLabel(this); iconLabel->setPixmap( m_itemIcons->getPixmap(entry.itemId, kSummaryIconSizePx)); - m_layout->addWidget(iconLabel); + addAndShow(m_layout, iconLabel); } else { - m_layout->addWidget( - new QLabel(QString::fromStdString(entry.itemId), this)); + addAndShow(m_layout, + new QLabel(QString::fromStdString(entry.itemId), this)); } - m_layout->addWidget(new QLabel(QString::number(entry.amount), this)); + addAndShow(m_layout, new QLabel(QString::number(entry.amount), this)); } }