Commit 9667add0 authored by Daniel Smith's avatar Daniel Smith

Replace DataVis with pureQML gauge

parent b4718e03
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtScxml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.5
Rectangle {
id: button
property alias text: text.text
border.width: 1
border.color: "white"
property real textHeight: height - 2
property real fontHeight: 0.3
property real implicitMargin: (width - text.implicitWidth) / 2
Text {
id: text
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: parent.textHeight
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: height * fontHeight
color: "#1b1c1d"
font.family: "Open Sans Regular"
}
MouseArea {
id: mouse
anchors.fill: parent
onClicked: button.clicked()
}
}
......@@ -13,8 +13,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
benchmark.cpp
benchmark.cpp \
main.cpp
RESOURCES += qml.qrc
......@@ -31,3 +31,6 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
HEADERS += \
benchmark.h
DISTFILES += \
Speedometer.qml
This diff is collapsed.
......@@ -18,19 +18,15 @@ Item {
// Battery liquid rotation
property real __bRotation: Math.max(-maxLiquidRotation, Math.min(root.rotation+90, maxLiquidRotation))
width: batteryImage.width
height: batteryImage.height
property string textureExtension: Qt.application.version === "5.6" ? ".png" : ".ktx"
Behavior on __bRotation {
SmoothedAnimation {
velocity: 3.0
duration: 500
}
}
width: batteryImage.width
height: batteryImage.height / 1.8
scale: 0.8
Image {
id: batteryBar
source: "images/battery_bar.png"
source: "images/battery_bar" + textureExtension
visible: false
}
......@@ -48,7 +44,7 @@ Item {
Emitter {
width: 8
height: parent.height
x: 20
x: 40
emitRate: root.charging ? 20 + 50*root.value : 2 + 5*root.value
lifeSpan: 3500
size: 32
......@@ -103,13 +99,16 @@ Item {
id: clipper
anchors.fill: parent
anchors.leftMargin: 40
anchors.rightMargin: 40
anchors.topMargin: 125
anchors.bottomMargin: -100
anchors.rightMargin: 20
clip: true
Image {
id: levelImage
source: "images/bar_level2.png"
x: shaderEffectItem.value * root.width + (Math.abs(-root.__bRotation)*(shaderEffectItem.value-0.5)*2.9) - 75
source: "images/bar_level2" + textureExtension
x: shaderEffectItem.value * root.width + (Math.abs(-root.__bRotation)*(shaderEffectItem.value-0.5)*2.9) - 165
visible: false
}
......@@ -160,6 +159,7 @@ Item {
group: "first"
width: 8
height: 8
x: 30
anchors.verticalCenter: parent.verticalCenter
emitRate: 100
lifeSpan: 1400
......@@ -185,41 +185,8 @@ Item {
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
x: 60
font.pixelSize: 26
color: "#404040"
style: Text.Outline
styleColor: "#ffffff"
opacity: root.charging ? 0.6 : 0
text: "Charging"
Behavior on opacity {
NumberAnimation { duration: 500; easing.type: Easing.InOutQuad }
}
}
Image {
id: batteryImage
source: "images/battery2.png"
}
Text {
anchors.centerIn: parent
y: 22
font.pixelSize: 48
style: Text.Outline
color: root.__batteryLow && !root.charging ? "#802020" : "#404040"
styleColor: "#ffffff"
font.bold: true
rotation: -root.rotation
text: (root.value*100).toFixed(0) + "%"
SequentialAnimation on opacity {
running: root.__batteryLow && !root.charging
loops: Animation.Infinite
alwaysRunToEnd: true
NumberAnimation { to: 0.5; duration: 200; easing.type: Easing.InOutQuad }
NumberAnimation { to: 1.0; duration: 200; easing.type: Easing.InOutQuad }
}
source: "images/battery2" + textureExtension
}
}
import QtQuick 2.0
Item {
id: root
width: 200
height: 112
property real value: 0
property real maximum: 1
property real minimum: 0
property int xMax: width - handle.width - 4
property alias text: sliderText.text
onValueChanged: updatePos();
onXMaxChanged: updatePos();
onMinimumChanged: updatePos();
function updatePos() {
if (maximum > minimum) {
var pos = 2 + (value - minimum) * root.xMax / (maximum - minimum);
pos = Math.min(pos, width - handle.width - 2);
pos = Math.max(pos, 2);
handle.x = pos;
} else {
handle.x = 2;
}
}
Rectangle {
id: backgroundBar
anchors.fill: parent
anchors.topMargin: 40
anchors.bottomMargin: 40
border.width: 1
border.color: "white"
opacity: 0.2
gradient: Gradient {
GradientStop { position: 0.0; color: "lightgray" }
GradientStop { position: 1.0; color: "gray" }
}
}
Rectangle {
id: filler
anchors.left: parent.left
anchors.right: handle.horizontalCenter
anchors.top: backgroundBar.top
anchors.bottom: backgroundBar.bottom
border.width: 1
border.color: "#202020"
gradient: Gradient {
GradientStop { position: 0.0; color: "#f0f0f0" }
GradientStop { position: 1.0; color: "#404040" }
}
}
Item {
id: handle
width: 80
height: parent.height
Image {
anchors.centerIn: parent
source: "images/handle.png"
}
Image {
id: handleHighlight
anchors.centerIn: parent
source: "images/toggle.png"
opacity: mouseArea.pressed ? 0.6 : 0
Behavior on opacity {
NumberAnimation { duration: 200 }
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.margins: -20
drag.target: parent
drag.axis: Drag.XAxis
drag.minimumX: 2
drag.maximumX: root.xMax+2
onPositionChanged: {
value = (maximum - minimum) * (handle.x-2) / root.xMax + minimum;
}
}
}
Text {
id: sliderText
anchors.centerIn: parent
font.pixelSize: 28
style: Text.Outline
styleColor: "white"
color: "black"
opacity: 0.4
}
}
import QtQuick 2.4
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
Item {
id: myGauge
property real size: 400;
property real angle: 60
// private:
width: size;
height: size;
Rectangle {
id: border
anchors.fill: parent
anchors.margins: - 10
color: "black";
radius: width / 2.0;
}
Rectangle {
id: background
anchors.fill: parent
color: "grey";
radius: myGauge.size / 2.0;
layer.enabled: true
// This item should be used as the 'mask'
layer.samplerName: "maskSource"
layer.effect: ShaderEffect {
property var colorSource: backgroundGradient;
fragmentShader: "
uniform lowp sampler2D colorSource;
uniform lowp sampler2D maskSource;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor =
texture2D(colorSource, qt_TexCoord0)
* texture2D(maskSource, qt_TexCoord0).a
* qt_Opacity;
}
"
}
Rectangle {
id: backgroundGradient;
width: 100
height: 100
RadialGradient{
cached: true
anchors.fill: parent
angle: -40
horizontalRadius: 80
verticalRadius: 150
gradient: Gradient {
GradientStop { position: 0; color: "#09203f" }
GradientStop { position: 1; color: "#537895" }
}
}
visible: false; // should not be visible on screen.
layer.enabled: true;
layer.smooth: true
}
}
Image {
id: needle
source: "images/bar_level2.png"
property real len: myGauge.size / 1.5;
property real w: 70;
width: w;
height: len
antialiasing: true;
transform: [
Rotation { origin.x:35; origin.y: 35; angle: myGauge.angle; }
, Translate { x: myGauge.size / 2.0 - needle.w / 2.0; y: myGauge.size / 2.0 - needle.w / 2.0 }
]
layer.enabled: true
// This item should be used as the 'mask'
layer.samplerName: "maskSource"
layer.effect: ShaderEffect {
property var colorSource: gradientRect;
fragmentShader: "
uniform lowp sampler2D colorSource;
uniform lowp sampler2D maskSource;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor =
texture2D(colorSource, qt_TexCoord0)
* texture2D(maskSource, qt_TexCoord0).a
* qt_Opacity;
}
"
}
Rectangle {
id: gradientRect;
width: 10
height: 20
gradient: Gradient {
GradientStop { position: 0.5; color: "#ff9a9e" }
GradientStop { position: 1; color: "#fad0c4" }
}
visible: false; // should not be visible on screen.
layer.enabled: true;
layer.smooth: true
}
}
//Animate needle
SequentialAnimation on angle{
loops: Animation.Infinite
NumberAnimation { to : 300; duration: 2000; easing.type: Easing.InOutCubic }
NumberAnimation { to : 60; duration: 3000; easing.type: Easing.InOutCubic }
}
Rectangle {
id: innerMask
anchors.fill: parent
anchors.margins: 55
color: "black";
radius: width / 2.0;
layer.enabled: true
// This item should be used as the 'mask'
layer.samplerName: "maskSource"
layer.effect: ShaderEffect {
property var colorSource: innerGradientRect;
fragmentShader: "
uniform lowp sampler2D colorSource;
uniform lowp sampler2D maskSource;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
gl_FragColor =
texture2D(colorSource, qt_TexCoord0)
* texture2D(maskSource, qt_TexCoord0).a
* qt_Opacity;
}
"
}
Rectangle {
id: innerGradientRect;
width: 80
height: 80
RadialGradient{
cached: true
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0; color: "#434343" }
GradientStop { position: 0.6; color: "#000000" }
}
}
visible: false; // should not be visible on screen.
layer.enabled: true;
layer.smooth: true
}
}
}
import QtQuick 2.0
Item {
id: root
width: 112
height: 112
property bool checked: false
property alias icon: buttonIcon.source
signal toggled
Image {
id: handle
anchors.verticalCenter: parent.verticalCenter
source: "images/handle.png"
}
Image {
id: toggle
anchors.centerIn: parent
source: "images/toggle.png"
opacity: checked ? 0.6 : 0
Behavior on opacity {
NumberAnimation { duration: 200 }
}
}
Image {
id: buttonIcon
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
checked = !checked
root.toggled();
}
}
}
#include <QObject>
#include <benchmark.h>
#include <QtDebug>
#include <QElapsedTimer>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QGuiApplication>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <cmath>
#include <iomanip>
void Benchmark::startTimer(){
}
void Benchmark::countFrame(){
qint64 frametime = timer.restart();
//Save the frame time, reset the timer, and take a memory measurement.
qint64 frametime = timer.nsecsElapsed();
timer.start();
if (frame % 10 == 0)
emit measureMemory();
int thisframe = static_cast<int>(frametime);
float thisframe = static_cast<float>(frametime)/1000000;
try{
frametimes[frame] = thisframe;
} catch (int e){
printf("frame.");
//No need to handle this. We probably just rendered extra frames before finished() completed.
}
//printf("%d,%d\n", frame, thisframe);
qDebug() << "frame " << frame << ": " << thisframe << " ms";
// qDebug() << "frame " << frame << ": " << thisframe << " ms"; //Turn this off for real runs.
frame+=1;
if (frame >= maxframes){
this->finished();
......@@ -33,6 +33,7 @@ void Benchmark::countFrame(){
}
void Benchmark::measureMem(){
//Uses OS-specific method to pull memory for this process
#ifdef _WIN32
//define something for Windows (32-bit and 64-bit, this part is common)
#elif __APPLE__
......@@ -61,7 +62,49 @@ void Benchmark::measureMem(){
qDebug() << "Virtual Memory (KB): " << shared_mem << " RSS (KB): " << rss << " Private Bytes (KB): " << (rss - shared_mem);
}
float Benchmark::calculateSD(float data[]){
//calculate the standard deviation for our results.
float sum = 0.0, mean, standardDeviation = 0.0;
int i;
for(i = 0; i < maxframes; ++i)
{
sum += data[i];
}
mean = sum/maxframes;
for(i = 0; i < maxframes; ++i)
standardDeviation += pow(data[i] - mean, 2);
return sqrt(standardDeviation / maxframes);
}
void Benchmark::finished(){
qDebug() << "\n-------- FINISHED TEST RUN --------\n";
QString frametimesCS;
for (int i = 0; i < maxframes; i++){
frametimesCS += QString::number(static_cast<double>(frametimes[i]), 'f', 2) + ((i < maxframes - 1) ? ",": "");
}
qDebug() << "Frame times (ms):" << frametimesCS;
int n = sizeof(frametimes)/sizeof(frametimes[0]);
int runtime = std::accumulate(frametimes, frametimes+n, 0);
qDebug() << "Finished" << maxframes << "frames in" << runtime << "ms" << "at" << (maxframes*1000) / runtime << "fps";
int startuptime = static_cast<int>(frametimes[0]);
qDebug() << "Start-up time:" << startuptime << "ms";
float meanFrametime = (static_cast<float>(runtime) - startuptime) / static_cast<float>(maxframes);
qDebug() << "Average Frame time:" << QString::number(static_cast<double>(meanFrametime), 'f', 2).toFloat() << "ms";
frametimes[0] = frametimes[1]; // hack to omit start-up time from our standard deviation calcuation.
float runtimeStdDev = calculateSD(frametimes);
qDebug() << "Standard Deviation:" << runtimeStdDev; // << "over" << maxframes << "frames";
qDebug() << "Coefficient of Variation:" << (runtimeStdDev / meanFrametime) * 100;
QCoreApplication::quit();
}
......@@ -70,18 +113,16 @@ int Benchmark::runBenchmark(QGuiApplication &app){
QObject::connect(this, &Benchmark::measureMemory,
this, &Benchmark::measureMem);
qDebug() << "Started timer.";
this->timer.start();
QQmlApplicationEngine engine(QUrl("qrc:/main.qml"));
if (engine.rootObjects().size() != 1)
return -1;
QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
//Finish timing after the first frame is ready.
QObject::connect(window, &QQuickWindow::frameSwapped,
this, &Benchmark::countFrame);
//QCoreApplication::instance(), &QCoreApplication::quit);
if (app.exec() != 0)
return -1;
//return timer.elapsed(); //change to print averages.
//return runBenchmark(startup);
}
......@@ -24,14 +24,13 @@ class Benchmark: public QObject{
QElapsedTimer timer;
int frame = 0;
int lastframetotal;
static const int maxframes = 15;
int frametimes [maxframes];
static const int maxframes = 100;
float frametimes [maxframes];
void finished();
void startTimer();
//void measureMem();
const int processID = static_cast<int>(QCoreApplication::applicationPid());
const int processID = static_cast<int>(QCoreApplication::applicationPid());
float calculateSD(float[]);
};
#endif // BENCHMARK_H
images/arrows.png

2.9 KB | W: | H:

images/arrows.png

10.3 KB | W: | H:

images/arrows.png
images/arrows.png
images/arrows.png
images/arrows.png
  • 2-up
  • Swipe
  • Onion skin
images/bar_level2.png

4.65 KB | W: | H:

images/bar_level2.png

7.73 KB | W: | H:

images/bar_level2.png
images/bar_level2.png
images/bar_level2.png
images/bar_level2.png
  • 2-up
  • Swipe
  • Onion skin
images/battery2.png

27.7 KB | W: | H:

images/battery2.png

33.4 KB | W: | H:

images/battery2.png
images/battery2.png
images/battery2.png
images/battery2.png
  • 2-up
  • Swipe
  • Onion skin
images/battery_bar.png

54.8 KB | W: | H:

images/battery_bar.png

62 KB | W: | H:

images/battery_bar.png
images/battery_bar.png
images/battery_bar.png
images/battery_bar.png
  • 2-up
  • Swipe
  • Onion skin
images/lightning.png

1.38 KB | W: | H:

images/lightning.png

4.16 KB | W: | H:

images/lightning.png
images/lightning.png
images/lightning.png
images/lightning.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -4,27 +4,6 @@
#include <QtCore/QElapsedTimer>
#include <benchmark.h>
int runBenchmark(std::function<qint64()> f) {
{
printf("Startup times (ms): [1st run, 2nd run]\n");
auto r = f();
if (r >= 0)
printf("%d,", static_cast<int>(r));
else
return -1;
}
{
auto r = f();
if (r >= 0)
printf("%d\n", static_cast<int>(r));
else
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
......@@ -36,22 +15,11 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
std::string version = std::to_string(QT_VERSION_MAJOR) + "." + std::to_string(QT_VERSION_MINOR);
QCoreApplication::setApplicationVersion(QString::fromUtf8(version.c_str()));
QGuiApplication app(argc, argv);
Benchmark benchmark;
/*
auto startup = [&app](){
QQmlApplicationEngine engine(QUrl("qrc:/main.qml"));
if (engine.rootObjects().size() != 1)
return -1;
QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
QObject::connect(window, &QQuickWindow::frameSwapped,
&benchmark, &Benchmark::countFrame);
//QCoreApplication::instance(), &QCoreApplication::quit);
if (app.exec() != 0)
return -1;
};
*/
//return runBenchmark(startup);
return benchmark.runBenchmark(app);
}
This diff is collapsed.
......@@ -2,11 +2,21 @@
<qresource prefix="/">
<file>main.qml</file>
<file>QUItBattery.qml</file>
<file>images/background2.jpg</file>
<file>images/bar_level2.png</file>
<file>images/battery_bar.png</file>
<file>images/lightning.png</file>