import QtQuick Item { id: root property string name: "nebula" property color color: Theme.textPrimary property int size: 16 property real value: 1 implicitWidth: size implicitHeight: size Accessible.ignored: true Canvas { id: canvas anchors.fill: parent antialiasing: true onPaint: root.paint(getContext("2d")) } onNameChanged: canvas.requestPaint() onColorChanged: canvas.requestPaint() onValueChanged: canvas.requestPaint() onWidthChanged: canvas.requestPaint() onHeightChanged: canvas.requestPaint() function paint(ctx) { ctx.reset() ctx.strokeStyle = root.color ctx.fillStyle = root.color ctx.lineCap = "round" ctx.lineJoin = "round" ctx.scale(width / 24, height / 24) switch (root.name) { case "nebula": paintNebula(ctx) break case "search": paintSearch(ctx) break case "wifi": paintWifi(ctx) break case "speaker": paintSpeaker(ctx) break case "battery": paintBattery(ctx) break case "power": paintPower(ctx) break case "restart": paintRestart(ctx) break case "folder": paintFolder(ctx) break case "globe": paintGlobe(ctx) break case "terminal": paintTerminal(ctx) break case "settings": paintSettings(ctx) break case "game": paintGame(ctx) break case "photo": paintPhoto(ctx) break case "music": paintMusic(ctx) break case "document": paintDocument(ctx) break case "application": paintApplication(ctx) break default: paintApplication(ctx) break } } function paintNebula(ctx) { ctx.beginPath() ctx.arc(12, 12, 4.2, 0, Math.PI * 2) ctx.fill() ctx.save() ctx.translate(12, 12) ctx.rotate(-26 * Math.PI / 180) ctx.scale(10 / 4.15, 1) ctx.lineWidth = 1.35 * (4.15 / 10) ctx.beginPath() ctx.arc(0, 0, 4.15, 0, Math.PI * 2) ctx.stroke() ctx.restore() } function paintSearch(ctx) { ctx.lineWidth = 1.6 ctx.beginPath() ctx.arc(11, 11, 6.25, 0, Math.PI * 2) ctx.stroke() ctx.beginPath() ctx.moveTo(15.8, 15.8) ctx.lineTo(20, 20) ctx.stroke() } function paintWifi(ctx) { const strength = root.value ctx.lineWidth = 1.6 ctx.globalAlpha = strength > 0 ? 1 : 0.28 ctx.beginPath() ctx.moveTo(4.8, 15.2) ctx.bezierCurveTo(8.8, 11.2, 15.2, 11.2, 19.2, 15.2) ctx.stroke() ctx.globalAlpha = strength > 1 ? 1 : 0.28 ctx.beginPath() ctx.moveTo(7.4, 17.4) ctx.bezierCurveTo(10, 14.9, 14, 14.9, 16.6, 17.4) ctx.stroke() ctx.globalAlpha = 1 ctx.beginPath() ctx.arc(12, 20, 1.15, 0, Math.PI * 2) ctx.fill() } function paintSpeaker(ctx) { ctx.beginPath() ctx.moveTo(4.5, 9.4) ctx.lineTo(7.6, 9.4) ctx.lineTo(12, 6.2) ctx.lineTo(12, 17.8) ctx.lineTo(7.6, 14.6) ctx.lineTo(4.5, 14.6) ctx.closePath() ctx.fill() ctx.lineWidth = 1.5 ctx.beginPath() ctx.arc(12.5, 12, 4.2, -0.7, 0.7) ctx.stroke() ctx.globalAlpha = 0.7 ctx.beginPath() ctx.arc(12.5, 12, 7.2, -0.85, 0.85) ctx.stroke() ctx.globalAlpha = 1 } function paintBattery(ctx) { ctx.lineWidth = 1.5 ctx.beginPath() roundedRect(ctx, 2.5, 7.25, 16.5, 9.5, 2) ctx.stroke() ctx.beginPath() roundedRect(ctx, 19.5, 10, 2, 4, 0.6) ctx.fill() const fillWidth = Math.max(1.5, (14 * Math.min(100, Math.max(0, root.value))) / 100) ctx.beginPath() roundedRect(ctx, 4.2, 9, fillWidth, 6, 1) ctx.fill() } function paintPower(ctx) { ctx.lineWidth = 1.7 ctx.beginPath() ctx.moveTo(12, 4.5) ctx.lineTo(12, 11.7) ctx.stroke() ctx.beginPath() ctx.arc(12, 13, 6.2, Math.PI * 1.15, Math.PI * -0.15, false) ctx.stroke() } function paintRestart(ctx) { ctx.lineWidth = 1.7 ctx.beginPath() ctx.arc(12, 12, 7, -0.2, Math.PI * 1.55, true) ctx.stroke() ctx.beginPath() ctx.moveTo(19, 5.2) ctx.lineTo(19, 9.6) ctx.lineTo(14.6, 9.6) ctx.stroke() } function paintApplication(ctx) { ctx.lineWidth = 1.5 ctx.beginPath() roundedRect(ctx, 4.2, 5.2, 15.6, 13.6, 2.2) ctx.stroke() ctx.beginPath() ctx.moveTo(4.2, 8.4) ctx.lineTo(19.8, 8.4) ctx.stroke() ctx.beginPath() ctx.arc(7, 6.8, 0.7, 0, Math.PI * 2) ctx.fill() ctx.beginPath() ctx.arc(9.4, 6.8, 0.7, 0, Math.PI * 2) ctx.fill() } function paintFolder(ctx) { ctx.beginPath() ctx.moveTo(3.5, 8.2) ctx.quadraticCurveTo(3.5, 6.4, 5.3, 6.4) ctx.lineTo(9.4, 6.4) ctx.lineTo(11, 8.2) ctx.lineTo(18.7, 8.2) ctx.quadraticCurveTo(20.5, 8.2, 20.5, 10) ctx.lineTo(20.5, 16.8) ctx.quadraticCurveTo(20.5, 18.6, 18.7, 18.6) ctx.lineTo(5.3, 18.6) ctx.quadraticCurveTo(3.5, 18.6, 3.5, 16.8) ctx.closePath() ctx.fill() } function paintGlobe(ctx) { ctx.lineWidth = 1.6 ctx.beginPath() ctx.arc(12, 12, 7.25, 0, Math.PI * 2) ctx.stroke() ctx.lineWidth = 1.4 ctx.save() ctx.translate(12, 12) ctx.scale(3.1 / 7.25, 1) ctx.beginPath() ctx.arc(0, 0, 7.25, 0, Math.PI * 2) ctx.stroke() ctx.restore() ctx.beginPath() ctx.moveTo(5.2, 12) ctx.lineTo(18.8, 12) ctx.stroke() } function paintTerminal(ctx) { ctx.lineWidth = 1.7 ctx.beginPath() ctx.moveTo(7, 9.2) ctx.lineTo(10.4, 12) ctx.lineTo(7, 14.8) ctx.stroke() ctx.beginPath() ctx.moveTo(12.2, 15.2) ctx.lineTo(17, 15.2) ctx.stroke() } function paintSettings(ctx) { ctx.beginPath() ctx.arc(12, 12, 2.4, 0, Math.PI * 2) ctx.fill() ctx.lineWidth = 1.6 const ticks = [ [12, 5.2, 12, 6.8], [12, 17.2, 12, 18.8], [5.2, 12, 6.8, 12], [17.2, 12, 18.8, 12], [7.2, 7.2, 8.3, 8.3], [15.7, 15.7, 16.8, 16.8], [16.8, 7.2, 15.7, 8.3], [8.3, 15.7, 7.2, 16.8] ] for (let i = 0; i < ticks.length; i++) { const t = ticks[i] ctx.beginPath() ctx.moveTo(t[0], t[1]) ctx.lineTo(t[2], t[3]) ctx.stroke() } } function paintGame(ctx) { ctx.lineWidth = 1.5 ctx.beginPath() ctx.moveTo(5.2, 10.4) ctx.lineTo(18.8, 10.4) ctx.quadraticCurveTo(20.4, 10.4, 20.3, 12.1) ctx.lineTo(19.8, 15.3) ctx.quadraticCurveTo(19.6, 16.9, 18.5, 16.9) ctx.lineTo(16.3, 16.9) ctx.lineTo(15, 15.1) ctx.lineTo(10, 15.1) ctx.lineTo(8.7, 16.9) ctx.lineTo(6.5, 16.9) ctx.quadraticCurveTo(5.4, 16.9, 5.2, 15.3) ctx.lineTo(4.7, 12.1) ctx.quadraticCurveTo(4.6, 10.4, 5.2, 10.4) ctx.closePath() ctx.stroke() ctx.beginPath() ctx.moveTo(8, 12.4) ctx.lineTo(8, 15.6) ctx.moveTo(6.4, 14) ctx.lineTo(9.6, 14) ctx.stroke() ctx.beginPath() ctx.arc(15.4, 13.2, 0.9, 0, Math.PI * 2) ctx.fill() ctx.beginPath() ctx.arc(17.2, 15, 0.9, 0, Math.PI * 2) ctx.fill() } function paintPhoto(ctx) { ctx.lineWidth = 1.5 ctx.beginPath() roundedRect(ctx, 4, 6.2, 16, 11.6, 2) ctx.stroke() ctx.beginPath() ctx.arc(9, 10.2, 1.3, 0, Math.PI * 2) ctx.fill() ctx.beginPath() ctx.moveTo(7.2, 15.8) ctx.lineTo(10.6, 12.4) ctx.lineTo(13.2, 15) ctx.lineTo(15.4, 12.9) ctx.lineTo(18.8, 15.8) ctx.stroke() } function paintMusic(ctx) { ctx.lineWidth = 1.6 ctx.beginPath() ctx.moveTo(10, 16.6) ctx.lineTo(10, 7.4) ctx.lineTo(18, 5.8) ctx.lineTo(18, 15.2) ctx.stroke() ctx.beginPath() ctx.arc(8.2, 16.6, 2.2, 0, Math.PI * 2) ctx.fill() ctx.beginPath() ctx.arc(16.2, 15.2, 2.2, 0, Math.PI * 2) ctx.fill() } function paintDocument(ctx) { ctx.lineWidth = 1.5 ctx.beginPath() ctx.moveTo(7, 5.5) ctx.lineTo(13.2, 5.5) ctx.lineTo(17.5, 10) ctx.lineTo(17.5, 18.5) ctx.quadraticCurveTo(17.5, 20, 16, 20) ctx.lineTo(7, 20) ctx.quadraticCurveTo(5.5, 20, 5.5, 18.5) ctx.lineTo(5.5, 7) ctx.quadraticCurveTo(5.5, 5.5, 7, 5.5) ctx.closePath() ctx.stroke() ctx.beginPath() ctx.moveTo(13.2, 5.5) ctx.lineTo(13.2, 10) ctx.lineTo(17.5, 10) ctx.stroke() ctx.beginPath() ctx.moveTo(8.8, 13.4) ctx.lineTo(15.2, 13.4) ctx.moveTo(8.8, 16.2) ctx.lineTo(13.2, 16.2) ctx.stroke() } function roundedRect(ctx, x, y, w, h, r) { const radius = Math.min(r, w / 2, h / 2) ctx.moveTo(x + radius, y) ctx.lineTo(x + w - radius, y) ctx.quadraticCurveTo(x + w, y, x + w, y + radius) ctx.lineTo(x + w, y + h - radius) ctx.quadraticCurveTo(x + w, y + h, x + w - radius, y + h) ctx.lineTo(x + radius, y + h) ctx.quadraticCurveTo(x, y + h, x, y + h - radius) ctx.lineTo(x, y + radius) ctx.quadraticCurveTo(x, y, x + radius, y) ctx.closePath() } }