Skip to content

About

Qt Quick/QML hi-fi faceplate UI and control library: 45 controls, a full Qt Quick Controls style, zero image assets.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

FIDELITY — Amplifier D707

A 1970s hi-fi faceplate rebuilt in Qt Quick, and the control library that came out of building it.

The D707 faceplate running

Every pixel above is drawn at run time. There are no PNGs, no SVGs, no icon font and no assets folder anywhere in the source. Knobs, faders, switches, lamps, the level window and every shadow are made from Rectangles, gradients and Context2D paths, so the whole thing stays sharp at any size and recolours from a single token file.


What is in here

Three pieces, sharing one set of drawing primitives:

The faceplate main.qml. The amplifier itself, rebuilt from the reference artwork.
controls/ 45 standalone controls with no QtQuick.Controls dependency, including the parts Qt has no equivalent for: Knob, Fader, VuScreen, LevelMeter, SevenSegment, CircularGauge, Led, TapeButton, LeverSwitch.
style/D707/ A real Qt Quick Controls style. All 53 stylable types in Qt 6.8. Drop it into an existing app and the app keeps working.

Both control sets draw from primitives/, so they look identical side by side.


Three faceplates

The colour comes from one token file, so a skin is a handful of values rather than a new set of graphics. Press 1, 2, 3 or Space to cycle, or pick a colour from the button in the top right.

Teal Ochre Grey

Those three are the reference artwork the faceplate was rebuilt from. How closely the running app matches them is measured below.


The control library, documented

Press G for a gallery that walks through every control, what it is for, and the properties you can set on it. It reflows from a wide desktop down to a narrow window.

The control gallery


The Qt Quick Controls style

Press N for a window that contains no custom types at all — every control in it is the stock QtQuick.Controls one, wearing the D707 style.

Stock Qt Quick Controls in the D707 style

This is the part that matters if you already have an app. Each file in style/D707/ is a QtQuick.Templates control with only its delegates replaced, so you keep everything Qt gives you:

  • keyboard navigation, focus handling and tab order
  • stepSize, snapMode, live, wheelEnabled, drag behaviour
  • mirroring for right-to-left languages
  • ToolTip attached properties, Dialog.standardButtons, ButtonGroup
  • the full property and signal surface of every control

The only thing added is an accent property on the pressable controls. It is the face colour, and the gradients, borders and shading all derive from it:

Button { text: "Delete"; accent: "#E45555" }
Slider { accent: "#F9D95C" }
Dial   { accent: "#4A8ED9" }

Leave it alone and you get machined grey.

Adopting it

Copy style/D707/ and primitives/ into your project and add them to your .qrc. In Qt 6 a custom style is a QML module, not a plain folder, so it needs three things:

1. A qmldir beside the style files

module D707
Button 1.0 Button.qml
Slider 1.0 Slider.qml
...

2. The module reachable at :/D707/, via an alias in your .qrc:

<file alias="D707/Button.qml">style/D707/Button.qml</file>

3. The style selected, and the resource root on the import path

qtquickcontrols2.conf:

[Controls]
Style=D707
FallbackStyle=Basic

main.cpp:

QQuickStyle::setFallbackStyle("Basic");
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");

The fallback matters. It is what Qt uses for any type the style does not provide, and it is what keeps a partial style from crashing an app.


How close is it to the original?

The faceplate was rebuilt by measuring the reference artwork rather than by eye: run-length scans for edges, colour sampling for every surface, and a numerical fit for the shadow falloff.

  • Mean absolute difference: 3.58 out of 255 across the whole 1472 × 987 frame
  • Knobs come in at 3.3; the panels and the level window are essentially exact
Reference artwork Headless render of the app

render.sh builds that render and writes render.png, which you can diff against docs/faceplate-teal.png to check a change has not drifted.


Resizing

The window fills. There is no fixed size and no letterboxing.

  • The faceplate is a RowLayout of four columns, each a ColumnLayout. Panel frames, margins and gaps all stretch.
  • Inside each frame the artwork keeps its original reference coordinates and rides one shared scale taken from the window, so a knob in SOURCE 1 is always the same size as the identical knob in SOURCE 2, whatever shape the window is.

Column and row sizes are solved directly against the reference grid rather than left to layout stretch factors. At the reference shape every element lands on its original pixel; at any other shape the solved units grow faster than the artwork scale, which is what guarantees a control can never overflow the frame holding it.


Checking your work

There is no compiler for QML delegates, so verify.py does what it can statically across all 125 QML files:

$ python3 verify.py
checked 125 QML files
all checks passed

Every rule in it exists because that exact mistake shipped once and cost a build cycle:

  • bracket balance, duplicate property assignments
  • QML ids that start with a capital letter, or that are JavaScript reserved words (native is one, and it fails with a parse error three lines later)
  • font.families, which is not assignable here, and CSS-style font stacks
  • types used without an import that resolves them
  • style files that import QtQuick.Controls, which is what they implement
  • implicitIndicator* on a template that has more than one indicator
  • style files missing from qmldir or from qml.qrc, which is what produces module "D707" is not installed

Building

Qt 6.5 or newer. Qt 6.8.8 is what this is developed against.

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/IfiDesign

If you change a file and the app does not seem to notice, touch qml.qrc so AUTORCC re-runs.

Keys

Key
1 2 3 Space Cycle the faceplate colour
G Open the control gallery
N Open the stock Qt Quick Controls window

Repository layout

main.qml              the faceplate
Gallery.qml           the documented control gallery
Native.qml            stock QtQuick.Controls, D707 style, zero custom types
primitives/           Style tokens, Raised, Recessed, SoftShadow, GripSurface,
                      Glyph, Cap, Caption
controls/             46 standalone controls
style/D707/           53 Qt Quick Controls style files + qmldir
gallery/              the gallery shell and its pages
verify.py             static checks
render.sh             headless render for pixel diffing
NOTES.md              how the reconstruction was done
ROADMAP.md            what is still missing, in priority order

Status

The faceplate, the control library and the style are all working. What is not done yet is written down in ROADMAP.md. The short version:

  • No style file reads palette yet, so an app that sets its own accent colour is ignored. This is the biggest blocker to real drop-in use.
  • No Accessible properties anywhere, so screen readers see nothing.
  • No run-time tests. verify.py reads the files, it never runs them.
  • No install rules, so the style only works from inside this repository.

No licence has been chosen yet.

About

Qt Quick/QML hi-fi faceplate UI and control library: 45 controls, a full Qt Quick Controls style, zero image assets.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages