Warning, /plasma/kinfocenter/Modules/energy/ui/Graph.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2015 David Edmundson <david@davidedmundson.co.uk> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 * 0006 */ 0007 0008 import QtQuick 2.3 0009 0010 /** 0011 * We need to draw a graph, all other libs are not suitable as we are basically 0012 * a connected scatter plot with non linear X spacing. 0013 * Currently this is not available in kdeclarative nor kqtquickcharts 0014 * 0015 * We only paint once, so canvas is fast enough for our purposes. 0016 * It is designed to look identical to those in ksysguard. 0017 */ 0018 0019 Canvas 0020 { 0021 width: 500 0022 height: 500 0023 id: canvas 0024 antialiasing: true 0025 0026 property int xPadding: 45 0027 property int yPadding: 40 0028 0029 property var data //expect an array of QPointF 0030 0031 property real yMax: 100 0032 property real xMax: 100 0033 property real yMin: 0 0034 property real xMin: 0 0035 property real yStep: 20 0036 0037 property string yUnits: "" 0038 property string xUnits: "" 0039 0040 property real xDuration: 3600 0041 property real xDivisions: 6 0042 property real xDivisionWidth: 600000 0043 property real xTicksAt: xTicksAtDontCare 0044 0045 //internal 0046 0047 property real plotWidth: width - xPadding * 1.5 0048 property real plotHeight: height - yPadding * 2 0049 0050 onDataChanged: { 0051 canvas.requestPaint(); 0052 } 0053 0054 //take a QPointF 0055 function scalePoint(plot, currentUnixTime) { 0056 var scaledX = (plot.x - (currentUnixTime / 1000 - xDuration)) / xDuration * plotWidth; 0057 var scaledY = (plot.y - yMin) * plotHeight / (yMax - yMin); 0058 0059 return Qt.point(xPadding + scaledX, 0060 height - yPadding - scaledY); 0061 } 0062 0063 SystemPalette { 0064 id: palette; 0065 colorGroup: SystemPalette.Active 0066 } 0067 0068 0069 onPaint: { 0070 var c = canvas.getContext('2d'); 0071 0072 c.clearRect(0,0, width, height) 0073 0074 //draw the background 0075 c.fillStyle = palette.base 0076 c.fillRect(xPadding, yPadding, plotWidth, plotHeight); 0077 0078 //reset for fonts and stuff 0079 c.fillStyle = palette.text 0080 0081 //Draw the lines 0082 0083 c.lineWidth = 1; 0084 c.lineJoin = 'round'; 0085 c.lineCap = 'round'; 0086 c.strokeStyle = 'rgba(255, 0, 0, 1)'; 0087 var gradient = c.createLinearGradient(0,0,0,height); 0088 gradient.addColorStop(0, 'rgba(255, 0, 0, 0.2)'); 0089 gradient.addColorStop(1, 'rgba(255, 0, 0, 0.05)'); 0090 c.fillStyle = gradient; 0091 0092 // For scaling 0093 var currentUnixTime = Date.now() 0094 var xMinUnixTime = currentUnixTime - xDuration * 1000 0095 0096 // Draw the line graph 0097 c.beginPath(); 0098 0099 var index = 0 0100 0101 while ((index < data.length - 1) && (data[index].x < (xMinUnixTime / 1000))) { 0102 index++ 0103 } 0104 0105 var firstPoint = scalePoint(data[index], currentUnixTime) 0106 c.moveTo(firstPoint.x, firstPoint.y) 0107 0108 var point 0109 for (var i = index + 1; i < data.length; i++) { 0110 if (data[i].x > (xMinUnixTime / 1000)) { 0111 point = scalePoint(data[i], currentUnixTime) 0112 c.lineTo(point.x, point.y) 0113 } 0114 } 0115 0116 c.stroke(); 0117 c.strokeStyle = 'rgba(0, 0, 0, 0)'; 0118 c.lineTo(point.x, height - yPadding); 0119 c.lineTo(firstPoint.x, height - yPadding); 0120 c.fill(); 0121 0122 c.closePath() 0123 0124 // Draw the frame on top 0125 0126 //draw an outline 0127 c.strokeStyle = 'rgba(0,50,0,0.02)'; 0128 c.lineWidth = 1; 0129 c.rect(xPadding - 1, yPadding - 1, plotWidth + 2, plotHeight + 2); 0130 0131 // Draw the Y value texts 0132 c.fillStyle = palette.text; 0133 c.textAlign = "right" 0134 c.textBaseline = "middle"; 0135 for(var i = 0; i <= yMax; i += yStep) { 0136 var y = scalePoint(Qt.point(0,i)).y; 0137 0138 c.fillText(i + canvas.yUnits, xPadding - 10, y); 0139 0140 //grid line 0141 c.moveTo(xPadding, y) 0142 c.lineTo(plotWidth + xPadding, y) 0143 } 0144 c.stroke() 0145 0146 // Draw the X value texts 0147 c.textAlign = "center" 0148 c.lineWidth = 1 0149 c.strokeStyle = 'rgba(%1, %2, %3, 0.15)'.arg(palette.text.r * 255).arg(palette.text.g * 255).arg(palette.text.b * 255) 0150 0151 var xDivisions = xDuration / xDivisionWidth * 1000 0152 var xGridDistance = plotWidth / xDivisions 0153 var xTickPos 0154 var xTickDateTime 0155 var xTickDateStr 0156 var xTickTimeStr 0157 0158 var currentDateTime = new Date() 0159 var lastDateStr = currentDateTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat) 0160 0161 var hours = currentDateTime.getHours() 0162 var minutes = currentDateTime.getMinutes() 0163 var seconds = currentDateTime.getSeconds() 0164 0165 var diff 0166 0167 switch (xTicksAt) { 0168 case xTicksAtTwelveOClock: 0169 diff = ((hours - 12) * 60 * 60 + minutes * 60 + seconds) 0170 break 0171 case xTicksAtFullHour: 0172 diff = (minutes * 60 + seconds) 0173 break 0174 case xTicksAtFullSecondHour: 0175 diff = (minutes * 60 + seconds) 0176 break 0177 case xTicksAtHalfHour: 0178 diff = ((minutes - 30) * 60 + seconds) 0179 break 0180 case xTicksAtTenMinutes: 0181 diff = ((minutes % 10) * 60 + seconds) 0182 break 0183 default: 0184 diff = 0 0185 } 0186 0187 var xGridOffset = plotWidth * (diff / xDuration) 0188 var dateChanged = false 0189 0190 var dashedLines = 50 0191 var dashedLineLength = plotHeight / dashedLines 0192 var dashedLineDutyCycle 0193 0194 for (var i = xDivisions; i >= -1; i--) { 0195 xTickPos = i * xGridDistance + xPadding - xGridOffset 0196 0197 if ((xTickPos > xPadding) && (xTickPos < plotWidth + xPadding)) 0198 { 0199 xTickDateTime = new Date(currentUnixTime - (xDivisions - i) * xDivisionWidth - diff * 1000) 0200 xTickDateStr = xTickDateTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat) 0201 xTickTimeStr = xTickDateTime.toLocaleTimeString(Qt.locale(), Locale.ShortFormat) 0202 0203 if (lastDateStr != xTickDateStr) { 0204 dateChanged = true 0205 } 0206 0207 if ((i % 2 == 0) || (xDivisions < 10)) 0208 { 0209 // Display the time 0210 c.fillText(xTickTimeStr, xTickPos, canvas.height - yPadding / 2) 0211 0212 // If the date has changed and is not the current day in a <= 24h graph, display it 0213 // Always display the date for 48h and 1 week graphs 0214 if (dateChanged || (xDuration > (60*60*48))) { 0215 c.fillText(xTickDateStr, xTickPos, canvas.height - yPadding / 4) 0216 dateChanged = false 0217 } 0218 0219 // Tick markers 0220 c.moveTo(xTickPos, canvas.height - yPadding) 0221 c.lineTo(xTickPos, canvas.height - (yPadding * 4) / 5) 0222 0223 dashedLineDutyCycle = 0.5 0224 } else { 0225 dashedLineDutyCycle = 0.1 0226 } 0227 0228 for (var j = 0; j < dashedLines; j++) { 0229 c.moveTo(xTickPos, yPadding + j * dashedLineLength) 0230 c.lineTo(xTickPos, yPadding + j * dashedLineLength + dashedLineDutyCycle * dashedLineLength) 0231 } 0232 lastDateStr = xTickDateStr 0233 } 0234 } 0235 c.stroke() 0236 } 0237 }