#include "ItemChipRow.h" #include #include "ItemChip.h" #include "ItemIconCache.h" namespace { // Size the item's colored square is drawn at inside a chip, in device-independent // pixels. Larger than the artwork it carries, which the square insets (REQ-UI-ITEM-ICON). const int kChipIconSizePx = 22; // Chips per row. Two fit the panel's capped width side by side; a third would force the // counts to shrink. const int kChipsPerRow = 2; } // namespace ItemChipRow::ItemChipRow(ItemIconCache* itemIcons, QWidget* parent) : QWidget(parent) , m_itemIcons(itemIcons) { m_layout = new QGridLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(4); } void ItemChipRow::setEntries(const std::vector& entries) { std::vector itemIds; itemIds.reserve(entries.size()); for (const Entry& entry : entries) { itemIds.push_back(entry.itemId); } // Only the set of items changing is a structural change; the counts change every // tick and must not cost a widget rebuild. if (itemIds != m_itemIds) { m_itemIds = std::move(itemIds); rebuildChips(entries); } for (std::size_t index = 0; index < entries.size(); ++index) { m_chips[index]->setCount(entries[index].countText); m_chips[index]->setSubLine(entries[index].subLine); } setVisible(!entries.empty()); } void ItemChipRow::rebuildChips(const std::vector& entries) { for (ItemChip* chip : m_chips) { m_layout->removeWidget(chip); chip->deleteLater(); } m_chips.clear(); for (std::size_t index = 0; index < entries.size(); ++index) { const std::string& itemId = entries[index].itemId; // The item's icon on its colored square (REQ-UI-ITEM-ICON). A missing icon file // is not an error: the chip then carries the square alone, and only an item with // no square either leaves the chip laid out around its count alone. const QPixmap icon = m_itemIcons->getSquarePixmap(itemId, kChipIconSizePx); 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); } }