Warning, /plasma/plasma-mobile/kcms/powermanagement/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 id: canvas 0022 antialiasing: true 0023 0024 readonly property real xTicksAtDontCare: 0 0025 readonly property real xTicksAtTwelveOClock: 1 0026 readonly property real xTicksAtFullHour: 2 0027 readonly property real xTicksAtHalfHour: 3 0028 readonly property real xTicksAtFullSecondHour: 4 0029 readonly property real xTicksAtTenMinutes: 5 0030 readonly property real xTicksAtFullTwoHours: 6 0031 0032 property int xPadding: 45 0033 property int yPadding: 40 0034 0035 property var data //expect an array of QPointF 0036 0037 property real yMax: 100 0038 property real xMax: 100 0039 property real yMin: 0 0040 property real xMin: 0 0041 property real yStep: 20 0042 0043 property real xDuration: 3600 0044 property real xDivisions: 6 0045 property real xDivisionWidth: 600000 0046 property real xTicksAt: xTicksAtDontCare 0047 0048 //internal 0049 0050 property real plotWidth: width - xPadding * 1.5 0051 property real plotHeight: height - yPadding * 2 0052 0053 onDataChanged: { 0054 canvas.requestPaint(); 0055 } 0056 0057 //take a QPointF 0058 function scalePoint(plot, currentUnixTime) { 0059 var scaledX = (plot.x - (currentUnixTime / 1000 - xDuration)) / xDuration * plotWidth; 0060 var scaledY = (plot.y - yMin) * plotHeight / (yMax - yMin); 0061 0062 return Qt.point(xPadding + scaledX, 0063 height - yPadding - scaledY); 0064 } 0065 0066 SystemPalette { 0067 id: palette; 0068 colorGroup: SystemPalette.Active 0069 } 0070 0071 0072 onPaint: { 0073 var c = canvas.getContext('2d'); 0074 0075 c.clearRect(0,0, width, height) 0076 0077 //draw the background 0078 c.fillStyle = palette.base 0079 c.fillRect(xPadding, yPadding, plotWidth, plotHeight); 0080 0081 //reset for fonts and stuff 0082 c.fillStyle = palette.text 0083 0084 //Draw the lines 0085 0086 c.lineWidth = 1; 0087 c.lineJoin = 'round'; 0088 c.lineCap = 'round'; 0089 c.strokeStyle = 'rgba(255, 0, 0, 1)'; 0090 var gradient = c.createLinearGradient(0,0,0,height); 0091 gradient.addColorStop(0, 'rgba(255, 0, 0, 0.2)'); 0092 gradient.addColorStop(1, 'rgba(255, 0, 0, 0.05)'); 0093 c.fillStyle = gradient; 0094 0095 // For scaling 0096 var currentUnixTime = Date.now() 0097 var xMinUnixTime = currentUnixTime - xDuration * 1000 0098 0099 // Draw the line graph 0100 c.beginPath(); 0101 0102 var index = 0 0103 0104 while ((index < data.length - 1) && (data[index].x < (xMinUnixTime / 1000))) { 0105 index++ 0106 } 0107 0108 var firstPoint = scalePoint(data[index], currentUnixTime) 0109 c.moveTo(firstPoint.x, firstPoint.y) 0110 0111 var point 0112 for (var i = index + 1; i < data.length; i++) { 0113 if (data[i].x > (xMinUnixTime / 1000)) { 0114 point = scalePoint(data[i], currentUnixTime) 0115 c.lineTo(point.x, point.y) 0116 } 0117 } 0118 0119 c.stroke(); 0120 c.strokeStyle = 'rgba(0, 0, 0, 0)'; 0121 c.lineTo(point.x, height - yPadding); 0122 c.lineTo(firstPoint.x, height - yPadding); 0123 c.fill(); 0124 0125 c.closePath() 0126 0127 // Draw the frame on top 0128 0129 //draw an outline 0130 c.strokeStyle = 'rgba(0,50,0,0.02)'; 0131 c.lineWidth = 1; 0132 c.rect(xPadding - 1, yPadding - 1, plotWidth + 2, plotHeight + 2); 0133 0134 // Draw the Y value texts 0135 c.fillStyle = palette.text; 0136 c.textAlign = "right" 0137 c.textBaseline = "middle"; 0138 for(var i = 0; i <= yMax; i += yStep) { 0139 var y = scalePoint(Qt.point(0,i)).y; 0140 0141 c.fillText(i18nc("%1 is a percentage value", "%1%", i), xPadding - 10, y); 0142 0143 //grid line 0144 c.moveTo(xPadding, y) 0145 c.lineTo(plotWidth + xPadding, y) 0146 } 0147 c.stroke() 0148 0149 // Draw the X value texts 0150 c.textAlign = "center" 0151 c.lineWidth = 1 0152 c.strokeStyle = 'rgba(0, 0, 0, 0.15)' 0153 0154 var xDivisions = xDuration / xDivisionWidth * 1000 0155 var xGridDistance = plotWidth / xDivisions 0156 var xTickPos 0157 var xTickDateTime 0158 var xTickDateStr 0159 var xTickTimeStr 0160 0161 var currentDateTime = new Date() 0162 var lastDateStr = currentDateTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat) 0163 0164 var hours = currentDateTime.getHours() 0165 var minutes = currentDateTime.getMinutes() 0166 var seconds = currentDateTime.getSeconds() 0167 0168 var diff 0169 0170 switch (xTicksAt) { 0171 case xTicksAtTwelveOClock: 0172 diff = ((hours - 12) * 60 * 60 + minutes * 60 + seconds) 0173 break 0174 case xTicksAtFullHour: 0175 diff = (minutes * 60 + seconds) 0176 break 0177 case xTicksAtFullSecondHour: 0178 diff = (minutes * 60 + seconds) 0179 break 0180 case xTicksAtHalfHour: 0181 diff = ((minutes - 30) * 60 + seconds) 0182 break 0183 case xTicksAtTenMinutes: 0184 diff = ((minutes % 10) * 60 + seconds) 0185 break 0186 default: 0187 diff = 0 0188 } 0189 0190 var xGridOffset = plotWidth * (diff / xDuration) 0191 var dateChanged = false 0192 0193 var dashedLines = 50 0194 var dashedLineLength = plotHeight / dashedLines 0195 var dashedLineDutyCycle 0196 0197 for (var i = xDivisions; i >= -1; i--) { 0198 xTickPos = i * xGridDistance + xPadding - xGridOffset 0199 0200 if ((xTickPos > xPadding) && (xTickPos < plotWidth + xPadding)) 0201 { 0202 xTickDateTime = new Date(currentUnixTime - (xDivisions - i) * xDivisionWidth - diff * 1000) 0203 xTickDateStr = xTickDateTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat) 0204 xTickTimeStr = xTickDateTime.toLocaleTimeString(Qt.locale(), Locale.ShortFormat) 0205 0206 if (lastDateStr != xTickDateStr) { 0207 dateChanged = true 0208 } 0209 0210 if ((i % 2 == 0) || (xDivisions < 10)) 0211 { 0212 // Display the time 0213 c.fillText(xTickTimeStr, xTickPos, canvas.height - yPadding / 2) 0214 0215 // If the date has changed and is not the current day in a <= 24h graph, display it 0216 // Always display the date for 48h and 1 week graphs 0217 if (dateChanged || (xDuration > (60*60*48))) { 0218 c.fillText(xTickDateStr, xTickPos, canvas.height - yPadding / 4) 0219 dateChanged = false 0220 } 0221 0222 // Tick markers 0223 c.moveTo(xTickPos, canvas.height - yPadding) 0224 c.lineTo(xTickPos, canvas.height - (yPadding * 4) / 5) 0225 0226 dashedLineDutyCycle = 0.5 0227 } else { 0228 dashedLineDutyCycle = 0.1 0229 } 0230 0231 for (var j = 0; j < dashedLines; j++) { 0232 c.moveTo(xTickPos, yPadding + j * dashedLineLength) 0233 c.lineTo(xTickPos, yPadding + j * dashedLineLength + dashedLineDutyCycle * dashedLineLength) 0234 } 0235 lastDateStr = xTickDateStr 0236 } 0237 } 0238 c.stroke() 0239 } 0240 }