/*SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>SPDX-License-Identifier: GPL-2.0-or-later*/import QtQuickimport QtQuick.Layoutsimport QtQuick.Controls as QQC2import QtQuick.Shapesimport org.kde.kirigami as Kirigamiimport org.kde.plasma.tablet.kcmimport org.kde.kcmutilsimport org.kde.kquickcontrolsKirigami.FormLayout {id: rootrequired property var dbrequired property var devicerequired property var tabletEventsreadonly property bool calibrationWindowOpen: calibrationWindow !== nullproperty Calibration calibrationWindowproperty string currentCalibrationSysNamesignal settingsRestored()RowLayout {Kirigami.FormData.label: i18nd("kcm_tablet", "Left-handed mode:")Kirigami.FormData.buddyFor: leftHandedCheckboxspacing: 0QQC2.CheckBox {id: leftHandedCheckboxtext: i18nc("Enable left-handed mode", "Enable")enabled: root.device && root.device.supportsLeftHandedchecked: root.device && root.device.leftHandedonCheckedChanged: root.device.leftHanded = checked}Kirigami.ContextualHelpButton {toolTipText: xi18nc("@info", "Tells the device to accommodate left-handed users. Effects will vary by device, but often it reverses the pad buttonsΚΌ functionality so the tablet can be used upside-down.")}SettingHighlighter {// No device has a default of left-handed, so this is always an explicit user choicehighlight: leftHandedCheckbox.checked}}Repeater {model: StylusButtonsModel {device: root.devicedb: root.db}delegate: ActionBinding {id: seqrequired property var modelDataKirigami.FormData.label: (buttonPressed ? "<b>" : "") + modelData.label + (buttonPressed ? "</b>" : "")property bool buttonPressed: falsename: modelData.nameConnections {target: root.tabletEventsfunction onToolButtonReceived(hardware_serial_hi, hardware_serial_lo, button, pressed) {if (button !== modelData.value) {return;}seq.buttonPressed = pressed}}Connections {target: rootfunction onSettingsRestored(): void {refreshInputSequence();}}function refreshInputSequence(): void {seq.inputSequence = kcm.toolButtonMapping(root.device.name, modelData.value)}Component.onCompleted: refreshInputSequence()onGotInputSequence: sequence => {kcm.assignToolButtonMapping(root.device.name, modelData.value, sequence)}SettingHighlighter {// Currently, application-defined is the defaulthighlight: seq.inputSequence.type !== InputSequence.ApplicationDefined}}}RowLayout {Kirigami.FormData.label: i18nd("kcm_tablet", "Pen Pressure:")Layout.fillWidth: truespacing: Kirigami.Units.smallSpacingColumnLayout {spacing: Kirigami.Units.smallSpacingPressureCurve {id: pressureCurveproperty bool loadedSettings: falseonControlPoint1Changed: saveSettings()onControlPoint2Changed: saveSettings()isDefault: root.device.pressureCurveIsDefaultLayout.fillWidth: trueComponent.onCompleted: reloadSettings()function reloadSettings(): void {if (!root.device) {return;}const points = kcm.fromSerializedCurve(root.device.pressureCurve);if (points.length === 2) {pressureCurve.controlPoint1 = points[0];pressureCurve.controlPoint2 = points[1];pressureCurve.forceReloadControlPoints();} else {pressureCurve.controlPoint1 = Qt.point(0.0, 0.0);pressureCurve.controlPoint2 = Qt.point(1.0, 1.0);}loadedSettings = true;}function saveSettings(): void {// We need to make sure not to re-save the settings we are loading in reloadSettings()if (!root.device || !loadedSettings) {return;}root.device.pressureCurve = kcm.toSerializedCurve(pressureCurve.controlPoint1, pressureCurve.controlPoint2);}Connections {target: root.device// For reloading the curve when it's reset/set to defaultfunction onPressureCurveChanged(): void {pressureCurve.reloadSettings();}}}RowLayout {QQC2.Label {text: i18ndc("kcm_tablet", "% of minimum pen pressure", "%1%", Math.round(root.device.pressureRangeMin * 100.0))}Item {Layout.fillWidth: true}QQC2.Label {text: i18ndc("kcm_tablet", "% of maximum pen pressure", "%1%", Math.round(root.device.pressureRangeMax * 100.0))}}}ColumnLayout {Layout.maximumHeight: pressureCurve.implicitHeightLayout.alignment: Qt.AlignTopspacing: Kirigami.Units.smallSpacingQQC2.Label {text: i18ndc("kcm_tablet", "100% or maximum pen pressure", "100%")}Item {Layout.fillHeight: true}QQC2.Label {text: i18ndc("kcm_tablet", "0% or zero pen pressure", "0%")}}Kirigami.ContextualHelpButton {toolTipText: i18ndc("kcm_tablet", "@info", "This curve controls the relationship between the pressure on the stylus and the pressure values received by applications.")}}RowLayout {Kirigami.FormData.label: i18ndc("kcm_tablet", "Pen pressure range", "Pressure Range:")spacing: Kirigami.Units.smallSpacingenabled: root.device.supportsPressureRangeLayout.fillWidth: trueQQC2.RangeSlider {from: 0to: 1first {value: root.device.pressureRangeMinonMoved: root.device.pressureRangeMin = first.value}second {value: root.device.pressureRangeMaxonMoved: root.device.pressureRangeMax = second.value}Layout.preferredWidth: pressureCurve.width}Item {Layout.fillWidth: true}Kirigami.ContextualHelpButton {toolTipText: i18ndc("kcm_tablet", "@info", "Pressure above or below the threshold will be clamped, and this becomes the new effective range.")}}QQC2.Button {// TODO: don't allow calibration across multiple screens againreadonly property bool supportsCalibration: root.device.supportsCalibrationMatrixtext: {if (supportsCalibration) {if (root.calibrationWindowOpen) {return i18nc("@action:button Calibration in progress", "Calibration in Progress");} else {return i18nc("@action:button Calibrate the pen display", "Calibrate");}} else {return i18nc("@action:button Pen display doesn't support calibration", "Calibration Not Supported");}}icon.name: "crosshairs"enabled: supportsCalibration && !root.calibrationWindowOpenonClicked: {const component = Qt.createComponent("Calibration.qml");if (component.status === Component.Ready) {let screenIndex = 0;for (let i = 0; i < Qt.application.screens.length; i++) {if (Qt.application.screens[i].name === root.device.outputName) {screenIndex = i;break;}}const window = component.createObject(root, {device: root.device, tabletEvents: root.tabletEvents});// We need to show the window first, because Qt will override screen based on position.// Working around QTBUG-129989window.show();// Then override the screen, try showing it again and now it'll be on the correct screen:window.screen = Qt.application.screens[screenIndex];window.showFullScreen();window.closing.connect((close) => {root.calibrationWindow = null;});root.currentCalibrationSysName = root.device.sysName;root.calibrationWindow = window;}}SettingHighlighter {highlight: !root.device.calibrationMatrixIsDefault}}ActionDialog {id: actionDialogparent: root.QQC2.Overlay.overlay}}