/* * Copyright (C) 2015 Malte Veerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ import QtQuick 2.6 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.2 import org.kde.kirigami 2.3 as Kirigami import Fancontrol.Qml 1.0 as Fancontrol import "math.js" as MoreMath import "colors.js" as Colors Item { id: root property QtObject fan property int margin: Kirigami.Units.smallSpacing property bool showControls: true property bool editable: true readonly property QtObject systemdCom: Fancontrol.Base.hasSystemdCommunicator ? Fancontrol.Base.systemdCom : null readonly property QtObject tempModel: Fancontrol.Base.tempModel readonly property real minTemp: Fancontrol.Base.minTemp readonly property real maxTemp: Fancontrol.Base.maxTemp onMinTempChanged: { meshCanvas.requestPaint(); curveCanvas.requestPaint(); } onMaxTempChanged: { meshCanvas.requestPaint(); curveCanvas.requestPaint(); } onFanChanged: curveCanvas.requestPaint() Item { id: graph property int fontSize: MoreMath.bound(8, height / 20 + 1, 16) property int verticalScalaCount: height > Kirigami.Units.gridUnit * 30 ? 11 : 6 property var horIntervals: MoreMath.intervals(root.minTemp, root.maxTemp, 10) anchors { left: parent.left right: parent.right top: parent.top bottom: root.showControls ? settingsArea.top : parent.bottom bottomMargin: root.margin } visible: graphBackground.height > 0 && graphBackground.width > 0 Item { id: verticalScala anchors { top: graphBackground.top bottom: graphBackground.bottom left: parent.left } width: MoreMath.maxWidth(children) + graph.fontSize / 3 Repeater { id: verticalRepeater model: graph.verticalScalaCount Text { x: verticalScala.width - implicitWidth - graph.fontSize / 3 y: graphBackground.height - graphBackground.height / (graph.verticalScalaCount - 1) * index - graph.fontSize * 2 / 3 horizontalAlignment: Text.AlignRight color: Kirigami.Theme.textColor text: Number(index * (100 / (graph.verticalScalaCount - 1))).toLocaleString(Qt.locale(), 'f', 0) + Qt.locale().percent font.pixelSize: graph.fontSize } } } Item { id: horizontalScala anchors { right: graphBackground.right bottom: parent.bottom left: graphBackground.left } height: graph.fontSize * 2 Repeater { model: graph.horIntervals.length; Text { x: graphBackground.scaleX(graph.horIntervals[index]) - width/2 y: horizontalScala.height / 2 - implicitHeight / 2 color: Kirigami.Theme.textColor text: Number(graph.horIntervals[index]).toLocaleString() + i18n("°C") font.pixelSize: graph.fontSize } } } Rectangle { id: graphBackground Kirigami.Theme.colorSet: Kirigami.Theme.View color: Kirigami.Theme.backgroundColor border.color: Kirigami.Theme.textColor border.width: 2 anchors { top: parent.top left: verticalScala.right bottom: horizontalScala.top right: parent.right topMargin: parent.fontSize rightMargin: parent.fontSize * 2 } function scaleX(temp) { return (temp - minTemp) * width / (maxTemp - minTemp); } function scaleY(pwm) { return height - pwm * height / 255; } function scaleTemp(x) { return x / width * (maxTemp - minTemp) + minTemp; } function scalePwm(y) { return 255 - y / height * 255; } Canvas { id: curveCanvas anchors.fill: parent anchors.margins: parent.border.width renderStrategy: Canvas.Threaded // renderTarget: Canvas.FramebufferObject onPaint: { var c = curveCanvas.getContext("2d"); c.clearRect(0, 0, width, height); if (!fan || !fan.hasTemp) { return; } var gradient = c.createLinearGradient(0, 0, width, 0); gradient.addColorStop(0, "rgb(0, 0, 255)"); gradient.addColorStop(1, "rgb(255, 0, 0)"); c.fillStyle = gradient; c.lineWidth = graph.fontSize / 3; c.strokeStyle = gradient; c.lineJoin = "round"; c.beginPath(); if (fan.minPwm == 0) { c.moveTo(stopPoint.centerX, height); } else { c.moveTo(0, stopPoint.centerY); c.lineTo(stopPoint.centerX, stopPoint.centerY); } c.lineTo(stopPoint.centerX, stopPoint.centerY); c.lineTo(maxPoint.centerX, maxPoint.centerY); c.lineTo(width, maxPoint.centerY); c.stroke(); c.lineTo(width, height); if (fan.minPwm == 0) { c.lineTo(stopPoint.centerX, height); } else { c.lineTo(0, height); } c.fill(); //blend graphBackground gradient = c.createLinearGradient(0, 0, 0, height); gradient.addColorStop(0, Colors.setAlpha(graphBackground.color, 0.5)); gradient.addColorStop(1, Colors.setAlpha(graphBackground.color, 0.9)); c.fillStyle = gradient; c.fill(); } Connections { target: fan onTempChanged: curveCanvas.requestPaint() onMinPwmChanged: curveCanvas.markDirty(Qt.rect(0, 0, stopPoint.x, stopPoint.y)) } } Canvas { id: meshCanvas anchors.fill: parent anchors.margins: parent.border.width renderStrategy: Canvas.Threaded // renderTarget: Canvas.FramebufferObject onPaint: { var c = meshCanvas.getContext("2d"); c.clearRect(0, 0, width, height); //draw mesh c.beginPath(); c.strokeStyle = Colors.setAlpha(Kirigami.Theme.textColor, 0.3); //horizontal lines for (var i=0; i<=100; i+=100/(graph.verticalScalaCount-1)) { var y = graphBackground.scaleY(i*2.55); if (i != 0 && i != 100) { for (var j=0; j<=width; j+=15) { c.moveTo(j, y); c.lineTo(Math.min(j+5, width), y); } } } //vertical lines if (graph.horIntervals.length > 1) { for (var i=1; i= height + 2*margin } }