qtdoc/examples/demos/calqlatr/content/Display.qml

168 lines
5.5 KiB
QML
Raw Normal View History

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Window
Item {
id: display
property int fontSize: 22
readonly property int maxDigits: Math.min((width / fontSize) + 1, 9)
readonly property color backgroundColor: "#262626"
readonly property color qtGreenColor: "#2CDE85"
property string displayedOperand: ""
readonly property string errorString: qsTr("ERROR")
readonly property bool isError: displayedOperand === errorString
property bool enteringDigits: false
function displayOperator(operator) {
calculationsListView.model.append({ "operator": operator, "operand": "" })
enteringDigits = true
calculationsListView.positionViewAtEnd()
}
function newLine(operator, operand) {
displayedOperand = displayNumber(operand)
calculationsListView.model.append({ "operator": operator, "operand": displayedOperand })
enteringDigits = false
calculationsListView.positionViewAtEnd()
}
function appendDigit(digit) {
if (!enteringDigits)
calculationsListView.model.append({ "operator": "", "operand": "" })
const i = calculationsListView.model.count - 1
calculationsListView.model.get(i).operand = calculationsListView.model.get(i).operand + digit
enteringDigits = true
calculationsListView.positionViewAtEnd()
}
function setDigit(digit) {
const i = calculationsListView.model.count - 1
calculationsListView.model.get(i).operand = digit
calculationsListView.positionViewAtEnd()
}
function backspace() {
const i = calculationsListView.model.count - 1
if (i >= 0) {
let operand = calculationsListView.model.get(i).operand
calculationsListView.model.get(i).operand = operand.toString().slice(0, -1)
return
}
return
}
function isOperandEmpty() {
const i = calculationsListView.model.count - 1
return i >= 0 ? calculationsListView.model.get(i).operand === "" : true
}
function isDisplayEmpty() {
const i = calculationsListView.model.count - 1
return i == -1 ? true : (i == 0 ? calculationsListView.model.get(0).operand === "" : false)
}
function clear() {
displayedOperand = ""
if (enteringDigits) {
const i = calculationsListView.model.count - 1
if (i >= 0)
calculationsListView.model.remove(i)
enteringDigits = false
}
}
function allClear()
{
display.clear()
calculationsListView.model.clear()
enteringDigits = false
}
// Returns a string representation of a number that fits in
// display.maxDigits characters, trying to keep as much precision
// as possible. If the number cannot be displayed, returns an
// error string.
function displayNumber(num) {
if (typeof(num) !== "number")
return errorString
// deal with the absolute
const abs = Math.abs(num)
if (abs.toString().length <= maxDigits) {
return isFinite(num) ? num.toString() : errorString
}
if (abs < 1) {
// check if abs < 0.00001, if true, use exponential form
// if it isn't true, we can round the number without losing
// too much precision
if (Math.floor(abs * 100000) === 0) {
const expVal = num.toExponential(maxDigits - 6).toString()
if (expVal.length <= maxDigits + 1)
return expVal
} else {
// the first two digits are zero and .
return num.toFixed(maxDigits - 2)
}
} else {
// if the integer part of num is greater than maxDigits characters, use exp form
const intAbs = Math.floor(abs)
if (intAbs.toString().length <= maxDigits)
return parseFloat(num.toPrecision(maxDigits - 1)).toString()
const expVal = num.toExponential(maxDigits - 6).toString()
if (expVal.length <= maxDigits + 1)
return expVal
}
return errorString
}
Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 8
color: display.backgroundColor
ListView {
id: calculationsListView
x: 5
y: 10
width: parent.width
height: parent.height - 2 * y
clip: true
delegate: Item {
height: display.fontSize * 1.1
width: calculationsListView.width
required property string operator
required property string operand
Text {
x: 6
font.pixelSize: display.fontSize
color: display.qtGreenColor
text: parent.operator
}
Text {
font.pixelSize: display.fontSize
anchors.right: parent.right
anchors.rightMargin: 16
text: parent.operand
color: "white"
}
}
model: ListModel { }
onHeightChanged: positionViewAtEnd()
}
}
}
}