Linux (Qt 6)
Tier 2 · Demi-supportedlinux-qt is a Tier 2 desktop target using Qt 6 Widgets through a C++ integration. Choose it
when a Qt interface fits your Linux audience. Available controls and services depend on the
Qt modules in the build; inspect those requirements before distributing the app.
Getting started
Qt 6 development packages and pkg-config are the requirement; build.rs builds the shim without
moc.
sudo apt install qt6-base-dev qt6-svg-dev pkg-config # Debian/Ubuntu
sudo dnf install qt6-qtbase-devel qt6-qtsvg-devel pkgconf # Fedora
brew install qt pkg-config # macOS, for the macos-qt dev combo
cargo install --git https://github.com/daybrite/day day-cli
day new app my-app --toolkit linux-qt
cd my-app
day launch -t linux-qt
Qt SVG development files (qt6-svg-dev on Debian/Ubuntu) are required to compile Day’s
native vector renderer. That package also installs the Qt SVG runtime used by bundled
vector icons and Day’s shared symbol fallbacks.
Sound effects play through libpulse, which a desktop already has (system requirements).
Two optional modules enable two pieces; without a module the build still succeeds and the piece degrades:
| Module | Enables | Without it |
|---|---|---|
qt6-webengine-dev (Qt6WebEngineWidgets) | webview() | a URL label; navigation calls become no-ops |
qt6-multimedia-dev (Qt6MultimediaWidgets) | media() | a URL label; play/pause become no-ops |
day doctor --toolkit qt probes Qt 6 Widgets, rcc, and the packaging tools
(flatpak-builder, linuxdeploy, linuxdeploy-plugin-qt); it does not check WebEngine or
Multimedia.
day pack -t linux-qt # single-file .flatpak (org.kde.Platform runtime) AND a portable .appimage
day pack produces both formats by default: the flatpak resolves Qt from its runtime; the
AppImage carries its own.
The webview crate declares a Qt WebEngine BaseApp requirement. If your binary links the engine,
day pack includes that base (about 87 MB of
Chromium), because no runtime ships it. Apps that don’t link it stay small; day pack inspects
the built binary to decide.
Caveats
toggleis aQCheckBox, because Qt Widgets has no native switch control, so the same Day code shows a checkbox here and a switch elsewhere.- The list is emulated. Day drives a
QScrollAreawith its own recycling rather thanQListView, so very large lists behave differently than a model/view Qt app would. - Forced light/dark needs Qt 6.8+.
DAY_THEMEusesQStyleHints::setColorScheme; on older Qt (Ubuntu 24.04 ships 6.4) Day falls back to the Fusion style with a hand-built dark palette. - No spell-check, because Qt ships none;
Cap::TextSpellCheckreports unsupported and the patch is a no-op. - Lottie and map have no Qt arm; each renders its placeholder.
cover()presents as a topmost window-sized child (no transition, programmatic dismissal only). - Qt on macOS and Windows (
macos-qt,windows-qt) is a development combo, and stays at Tier 4, soday packskips it. Windows builds against MSYS2’s Qt 6 with a GNU Rust toolchain (setup) and is marked experimental in CI. MSYS2 has no Qt 6 WebEngine, so the web view degrades to its URL label there. CI’s x86-64 MinGWldadditionally drops external piece renderer registrations, so those pieces draw placeholders on that build; a clang/lldMSYS2 environment keeps them.
What each piece becomes
The generated coverage matrix, checked in CI, covers every backend; this table adds links and notes.
| Day piece | Qt class |
|---|---|
column / row / nav_stack / section | QWidget (Day owns layout) |
label | QLabel |
button | QPushButton |
toggle | QCheckBox; see the caveat above |
slider | QSlider |
text_field | QLineEdit |
secure_field | QLineEdit in Password echo mode |
text_area | QPlainTextEdit |
picker().menu() | QComboBox |
picker().segmented() | checkable QPushButtons in an exclusive group |
picker().inline() | QRadioButtons in an exclusive group |
progress(f) | QProgressBar |
spinner() | QProgressBar in busy mode (Qt has no spinner widget) |
divider | QFrame (HLine) |
scroll | QScrollArea |
list | QScrollArea with Day-side recycling |
nav (split) | QSplitter; the stack header adds a QToolButton |
nav_menu | QListWidget |
tabs | QTabWidget |
image | QLabel subclass painting a scaled pixmap |
vector | the same QLabel subclass painting the raster cache PNG (.tint has no Qt arm yet; glyphs draw as authored) |
canvas | QWidget subclass painting with QPainter |
| dialogs / alerts | QMessageBox |
| prompts | QInputDialog |
| file dialogs | QFileDialog |
| menu bar / context menus | QMenuBar / QMenu |
external activity() | QProgressBar (busy) |
external combobox() | editable QComboBox |
external search_field() | QLineEdit with a clear button and a find icon |
external date_picker() | QDateEdit with a calendar popup, or QCalendarWidget inline |
external time_picker() | QTimeEdit |
external webview() | QWebEngineView |
external media() | QMediaPlayer + QVideoWidget |
Text measurement asks QLabel for its natural width with wrapping temporarily off, then
heightForWidth at the granted width; the text area uses QTextDocument. Everything else uses
sizeHint().