2023-10-02 09:20:35 +00:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
2022-06-03 11:26:02 +00:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
2018-06-26 13:53:07 +00:00
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
pragma ComponentBehavior: Bound
|
|
|
|
|
2020-12-01 12:57:32 +00:00
|
|
|
import QtQuick
|
|
|
|
import QtQuick.Window
|
2018-06-26 13:53:07 +00:00
|
|
|
|
|
|
|
Item {
|
|
|
|
id: display
|
2023-10-31 13:48:04 +00:00
|
|
|
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: ""
|
2023-10-02 09:20:35 +00:00
|
|
|
readonly property string errorString: qsTr("ERROR")
|
2021-09-14 08:36:23 +00:00
|
|
|
readonly property bool isError: displayedOperand === errorString
|
2023-10-31 13:48:04 +00:00
|
|
|
property bool enteringDigits: false
|
2018-06-26 13:53:07 +00:00
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
function displayOperator(operator) {
|
|
|
|
calculationsListView.model.append({ "operator": operator, "operand": "" })
|
2018-06-26 13:53:07 +00:00
|
|
|
enteringDigits = true
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.positionViewAtEnd()
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
function newLine(operator, operand) {
|
2018-06-26 13:53:07 +00:00
|
|
|
displayedOperand = displayNumber(operand)
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.model.append({ "operator": operator, "operand": displayedOperand })
|
2018-06-26 13:53:07 +00:00
|
|
|
enteringDigits = false
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.positionViewAtEnd()
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
function appendDigit(digit) {
|
2018-06-26 13:53:07 +00:00
|
|
|
if (!enteringDigits)
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.model.append({ "operator": "", "operand": "" })
|
2023-10-31 13:48:04 +00:00
|
|
|
const i = calculationsListView.model.count - 1
|
|
|
|
calculationsListView.model.get(i).operand = calculationsListView.model.get(i).operand + digit
|
2018-06-26 13:53:07 +00:00
|
|
|
enteringDigits = true
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.positionViewAtEnd()
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
function setDigit(digit) {
|
2023-10-31 13:48:04 +00:00
|
|
|
const i = calculationsListView.model.count - 1
|
|
|
|
calculationsListView.model.get(i).operand = digit
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.positionViewAtEnd()
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-31 13:48:04 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2023-10-02 09:20:35 +00:00
|
|
|
function clear() {
|
2018-06-26 13:53:07 +00:00
|
|
|
displayedOperand = ""
|
|
|
|
if (enteringDigits) {
|
2023-10-02 09:20:35 +00:00
|
|
|
const i = calculationsListView.model.count - 1
|
2018-06-26 13:53:07 +00:00
|
|
|
if (i >= 0)
|
2023-10-02 09:20:35 +00:00
|
|
|
calculationsListView.model.remove(i)
|
2018-06-26 13:53:07 +00:00
|
|
|
enteringDigits = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-31 13:48:04 +00:00
|
|
|
function allClear()
|
|
|
|
{
|
|
|
|
display.clear()
|
|
|
|
calculationsListView.model.clear()
|
|
|
|
enteringDigits = false
|
|
|
|
}
|
|
|
|
|
2018-06-26 13:53:07 +00:00
|
|
|
// 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) {
|
2023-10-02 09:20:35 +00:00
|
|
|
if (typeof(num) !== "number")
|
2023-10-31 13:48:04 +00:00
|
|
|
return errorString
|
2018-06-26 13:53:07 +00:00
|
|
|
|
2023-10-31 13:48:04 +00:00
|
|
|
// deal with the absolute
|
|
|
|
const abs = Math.abs(num)
|
2018-06-26 13:53:07 +00:00
|
|
|
|
2023-10-31 13:48:04 +00:00
|
|
|
if (abs.toString().length <= maxDigits) {
|
|
|
|
return isFinite(num) ? num.toString() : errorString
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
2023-10-31 13:48:04 +00:00
|
|
|
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
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
2023-10-31 13:48:04 +00:00
|
|
|
return errorString
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Item {
|
2023-10-31 13:48:04 +00:00
|
|
|
anchors.fill: parent
|
2018-06-26 13:53:07 +00:00
|
|
|
|
|
|
|
Rectangle {
|
2023-10-31 13:48:04 +00:00
|
|
|
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"
|
|
|
|
}
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
2023-10-31 13:48:04 +00:00
|
|
|
model: ListModel { }
|
|
|
|
onHeightChanged: positionViewAtEnd()
|
2018-06-26 13:53:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|