// A miniature of the real desktop that redraws as you change Appearance. // // The point is that "outer gaps 24" and "radius 9" mean nothing as numbers. This // shows two tiled windows at the settings currently in effect: the focused one // wearing the prism border and its glow, the unfocused one carrying the // inactive-opacity setting, both inside real gaps at a real corner radius. // // Geometry is scaled by the ratio between this preview's width and the actual // monitor's, so proportions are honest rather than decorative -- a 10px gap on // a 4500px display genuinely is almost invisible, and the preview says so. // // Everything here is driven by bindings on DesktopPreferences, so the preview // shows what is actually stored and applied. It has no state of its own and // nothing animates while idle. import QtQuick import QtQuick.Effects import qs.config import qs.services Rectangle { id: root implicitHeight: 232 radius: Theme.cardRadius clip: true border.width: 1 border.color: Theme.alpha(Theme.fg, 0.09) // Falls back to a sane width if the monitor has not been read yet, so the // preview is never wrong by a factor of ten on first paint. readonly property real monitorWidth: SystemSettings.monitorWidth > 0 ? SystemSettings.monitorWidth : 3000 readonly property real scale: width > 0 ? width / root.monitorWidth : 0.25 readonly property int gapsIn: DesktopPreferences.get("gapsIn") readonly property int gapsOut: DesktopPreferences.get("gapsOut") readonly property int borderSize: DesktopPreferences.get("borderSize") readonly property int rounding: DesktopPreferences.get("windowRounding") readonly property real inactiveOpacity: DesktopPreferences.get("inactiveOpacity") readonly property bool shadowOn: DesktopPreferences.get("shadowEnabled") readonly property int shadowRange: DesktopPreferences.get("shadowRange") readonly property bool glowOn: DesktopPreferences.get("glowEnabled") readonly property int glowRange: DesktopPreferences.get("glowRange") // Scaled geometry, floored so a small-but-nonzero setting stays visible // rather than rounding away to nothing. function px(value: real): real { return value <= 0 ? 0 : Math.max(1, value * root.scale); } // Stands in for the wallpaper. Static: an animated gradient here would // repaint forever behind a settings page. gradient: Gradient { orientation: Gradient.Vertical GradientStop { position: 0.0; color: "#2b3050" } GradientStop { position: 1.0; color: "#241f33" } } // The bar, so the preview reads as this desktop and not a generic one. Rectangle { id: miniBar anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: 20 color: Theme.alpha(Theme.bgDark, 0.4) border.width: 0 Row { anchors.left: parent.left anchors.leftMargin: 9 anchors.verticalCenter: parent.verticalCenter spacing: 4 Repeater { model: 3 Rectangle { required property int index width: index === 0 ? 12 : 5 height: 5 radius: 2.5 border.width: 0 color: index === 0 ? Theme.accent : Theme.alpha(Theme.fg, 0.3) anchors.verticalCenter: parent.verticalCenter } } } Text { anchors.centerIn: parent text: "Panama" color: Theme.alpha(Theme.fg, 0.45) font.family: Theme.fontFamily font.pixelSize: 9 } } Row { id: tiles anchors.top: miniBar.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: root.px(root.gapsOut) spacing: root.px(root.gapsIn) * 2 MiniWindow { width: (tiles.width - tiles.spacing) / 2 height: tiles.height focused: true } MiniWindow { width: (tiles.width - tiles.spacing) / 2 height: tiles.height focused: false } } component MiniWindow: Item { id: win required property bool focused // The gradient border is drawn as a filled rounded rect with the window // body inset on top of it: QML's Rectangle border takes a colour, not a // gradient, and the prism border is the whole signature here. Rectangle { id: frame anchors.fill: parent radius: root.px(root.rounding) border.width: 0 visible: win.focused && root.borderSize > 0 gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0.0; color: Theme.accent } GradientStop { position: 1.0; color: Theme.accentSecondary } } } Rectangle { id: body anchors.fill: parent anchors.margins: win.focused ? root.px(root.borderSize) : 0 radius: Math.max(0, root.px(root.rounding) - (win.focused ? root.px(root.borderSize) : 0)) color: Theme.alpha(Theme.bgDark, 0.92) opacity: win.focused ? 1.0 : root.inactiveOpacity border.width: win.focused ? 0 : 1 border.color: Theme.alpha(Theme.gutter, 0.6) clip: true Rectangle { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: 13 color: Theme.alpha(Theme.fg, 0.05) border.width: 0 } Column { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.topMargin: 22 anchors.margins: 10 spacing: 5 Repeater { model: [1.0, 0.74, 0.52] Rectangle { required property real modelData width: parent.width * modelData height: 4 radius: 2 border.width: 0 color: Theme.alpha(Theme.fg, win.focused ? 0.2 : 0.13) } } } Text { anchors.left: parent.left anchors.bottom: parent.bottom anchors.margins: 8 text: win.focused ? "focused" : "unfocused" color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: 9 } } // Shadow and glow both come from MultiEffect. Only the focused window // gets the glow, matching looks.lua where glow.color_inactive is fully // transparent. MultiEffect { anchors.fill: body source: body visible: root.shadowOn || (win.focused && root.glowOn) z: -1 shadowEnabled: true shadowColor: win.focused && root.glowOn ? Theme.alpha(Theme.accent, 0.5) : Theme.alpha("#15161e", 0.85) shadowBlur: win.focused && root.glowOn ? Math.min(1.0, root.px(root.glowRange) / 12) : Math.min(1.0, root.px(root.shadowRange) / 24) shadowVerticalOffset: win.focused && root.glowOn ? 0 : root.px(4) shadowHorizontalOffset: 0 } } }