List View
A virtualised list of themed item rows, for a set too large to be one widget per row.
#include <QApplication>
#include <QFile>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QStandardItemModel>
#include <QUrl>
#include <QVBoxLayout>
#include <array>
#ifdef SHADCN_GALLERY_MEDIA
#include <shadcn/media.hpp>
#endif
#include <shadcn/shadcn.hpp>
QWidget* example(QWidget* parent = nullptr) {
using namespace shadcn;
auto* canvas = new QWidget(parent);
canvas->setAutoFillBackground(true);
auto* outer = new QHBoxLayout(canvas);
outer->setContentsMargins(32, 32, 32, 32);
auto* host = new QWidget(canvas);
auto* layout = new QVBoxLayout(host);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(16);
outer->addStretch();
outer->addWidget(host, 0, Qt::AlignCenter);
outer->addStretch();
// A course list: the shapes a library actually fills rows with, and one
// heading row among them so the heading treatment is visible.
auto* list = new ListView(host);
list->setFixedSize(400, 320);
list->setCompactBelow(260);
auto* model = new QStandardItemModel(list);
const auto row = [](const QString& title, const QString& description,
const QString& trailing) {
auto* item = new QStandardItem(title);
item->setData(description, static_cast<int>(RowRole::Description));
item->setData(trailing, static_cast<int>(RowRole::TrailingText));
return item;
};
auto* heading = new QStandardItem(QStringLiteral("In progress"));
heading->setData(true, static_cast<int>(RowRole::Heading));
heading->setFlags(Qt::ItemIsEnabled);
model->appendRow(heading);
model->appendRow(row(QStringLiteral("Systems 101"), QStringLiteral("Lesson 4 of 12"), QStringLiteral("41%")));
model->appendRow(row(QStringLiteral("Signals 201"), QStringLiteral("Lesson 2 of 9"), QStringLiteral("22%")));
model->appendRow(row(QStringLiteral("Probability 150"), QStringLiteral("Lesson 11 of 14"), QStringLiteral("79%")));
model->appendRow(row(QStringLiteral("Linear Algebra"), QStringLiteral("Lesson 1 of 20"), QStringLiteral("5%")));
model->appendRow(row(QStringLiteral("Compilers 310"), QStringLiteral("Lesson 7 of 8"), QStringLiteral("88%")));
list->setModel(model);
list->setCurrentIndex(model->index(2, 0));
layout->addWidget(list);
return canvas;
}
Installation
- Source
- Installed package
add_subdirectory(shadcn-cpp)
target_link_libraries(app PRIVATE shadcn::widgets)
find_package(shadcn CONFIG REQUIRED)
target_link_libraries(app PRIVATE shadcn::widgets)
Usage
ListView is a QListView, so a caller fills a model and the rows on screen are
the only rows built. The title comes from Qt::DisplayRole; the rest of a row
comes from a RowRole.
#include <QStandardItemModel>
#include <shadcn/rows.hpp>
shadcn::ListView list(parent);
auto* model = new QStandardItemModel(&list);
auto* item = new QStandardItem(QStringLiteral("Systems 101"));
item->setData(QStringLiteral("Lesson 4 of 12"),
static_cast<int>(shadcn::RowRole::Description));
item->setData(QStringLiteral("41%"),
static_cast<int>(shadcn::RowRole::TrailingText));
model->appendRow(item);
list.setModel(model);
list.setCurrentIndex(model->index(0, 0));
Set RowRole::Heading on a row to make it a label for the rows under it rather
than a target: it takes no fill, no ring and no selection.
auto* heading = new QStandardItem(QStringLiteral("In progress"));
heading->setData(true, static_cast<int>(shadcn::RowRole::Heading));
heading->setFlags(Qt::ItemIsEnabled);
setCompactBelow gives the rows a density switch the caller does not have to
own: below the given height the rows become shorter, and a compact row is still
the same row.
list.setCompactBelow(400);
API
| Member | Purpose |
|---|---|
setCompact(bool) | Sets the row density directly. |
compactRows() | The current density. |
setCompactBelow(int) | The height at which rows become compact. Zero disables the switch. |
compactBelow() | That height. |
rowHeight() | The height one row occupies now. |
visibleRowRects() | The rectangles of the rows on screen. |
RowRole
| Role | Carries |
|---|---|
Qt::DisplayRole | The title. |
Description | The muted line under the title. |
Leading | A QPixmap before the text. |
Trailing | A QPixmap after the text. |
TrailingText | A short muted label on the trailing side. |
Heading | Marks a row as a label rather than a target. |
Notes
Every row is the same height, so a description occupies the second line whether or not it has text. A view whose rows differ in height has to measure all of them to find where the next one starts, which is the difference between paging through a library and walking it.
A selected row takes the accent fill and the accent foreground. The page foreground on an accent fill is the usual way a themed list loses contrast, and it looks right until the text is measured.