/*SPDX-FileCopyrightText: 2025 Oliver Beard <olib141@outlook.com>SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL*/import QtQuickimport QtQuick.Layoutsimport QtQuick.Controls as QQC2import org.kde.kcmutils as KCMimport org.kde.kirigami as Kirigamiimport org.kde.kquickcontrols as KQuickControlsimport org.kde.kwindowsystemKirigami.Form {id: pageLayoutcomponent FullScreenZoomSettingsModel : ObjectModel {id: objectModelproperty bool visible: kcm.zoomMagnifierSettings.zoomKirigami.FormEntry {visible: objectModel.visibletitle: i18nc("@label:spinbox", "Show pixel grid at zoom level:")contentItem: QQC2.SpinBox {id: zoomPixelGridZoomSpinBoxfrom: toInt(0)to: toInt(100)stepSize: toInt(1)validator: IntValidator {bottom: Math.min(zoomPixelGridZoomSpinBox.from, zoomPixelGridZoomSpinBox.to)top: Math.max(zoomPixelGridZoomSpinBox.from, zoomPixelGridZoomSpinBox.to)}textFromValue: (value, locale) => fromInt(value).toLocaleString(locale, 'f', 2)valueFromText: (text, locale) => Math.round(toInt(Number.fromLocaleString(locale, text)))value: toInt(kcm.zoomMagnifierSettings.zoomPixelGridZoom)onValueModified: kcm.zoomMagnifierSettings.zoomPixelGridZoom = fromInt(value)function toInt(value: double) : int {return value * 100;}function fromInt(value: int) : double {return value / 100;}KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomPixelGridZoom"}}}Kirigami.FormEntry {visible: objectModel.visibletitle: i18nc("@label:listbox", "Pointer tracking:")contentItem: QQC2.ComboBox {delegate: QQC2.ItemDelegate {id: delegaterequired property string titlerequired property string descriptionwidth: parent?.width ?? 0text: delegate.titlecontentItem: Kirigami.TitleSubtitle {title: delegate.titlesubtitle: delegate.descriptionfont: delegate.fontselected: delegate.highlighted || delegate.downwrapMode: Text.Wrap}}model: [{title: i18nc("@item:inlistbox", "Proportional"),description: i18nc("@item:inlistbox", "Zoom area moves in sync with pointer"),settingIndex: 0},{title: i18nc("@item:inlistbox", "Centered"),description: i18nc("@item:inlistbox", "Pointer stays centered on-screen, except near screen edges"),settingIndex: 1},{title: i18nc("@item:inlistbox", "Centered (Strict)"),description: i18nc("@item:inlistbox", "Pointer stays centered on-screen, even near screen edges"),settingIndex: 4},{title: i18nc("@item:inlistbox", "Push"),description: i18nc("@item:inlistbox", "Pointer pushes zoom area at screen edges"),settingIndex: 2},{title: i18nc("@item:inlistbox", "Disabled"),description: i18nc("@item:inlistbox", "Zoom area doesn't follow pointer"),settingIndex: 3}]textRole: "title"currentIndex: model.findIndex(m => m.settingIndex === kcm.zoomMagnifierSettings.zoomMouseTracking)onActivated: index => kcm.zoomMagnifierSettings.zoomMouseTracking = model[index].settingIndexLayout.preferredWidth: Kirigami.Units.gridUnit * 15KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomMouseTracking"}}}Kirigami.FormEntry {visible: objectModel.visiblecontentItem: QQC2.CheckBox {text: i18nc("@option:check", "Sharpen screen content while zoomed in")checked: kcm.zoomMagnifierSettings.zoomUsePatternUpscaleronCheckedChanged: kcm.zoomMagnifierSettings.zoomUsePatternUpscaler = checkedKCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomUsePatternUpscaler"}}}Kirigami.FormEntry {visible: objectModel.visiblecontentItem: QQC2.CheckBox {text: i18nc("@option:check", "Enable text caret tracking")checked: kcm.zoomMagnifierSettings.zoomEnableTextCaretTrackingonCheckedChanged: kcm.zoomMagnifierSettings.zoomEnableTextCaretTracking = checkedKCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomEnableTextCaretTracking"}}}}component MagnifierZoomSettingsModel : ObjectModel {id: objectModelproperty bool visible: kcm.zoomMagnifierSettings.magnifierKirigami.FormEntry {visible: objectModel.visibletitle: i18nc("@label:spinbox", "Width:")contentItem: QQC2.SpinBox {id: magnifierWidthSpinBoxfrom: 100to: 2000stepSize: 10validator: IntValidator {bottom: Math.min(magnifierWidthSpinBox.from, magnifierWidthSpinBox.to)top: Math.max(magnifierWidthSpinBox.from, magnifierWidthSpinBox.to)}textFromValue: (value, locale) => { return i18ncp("short for pixel(s)", "%1 px", "%1 px", value); }valueFromText: (text, locale) => { return Number.fromLocaleString(locale, text.replace(i18nc("short for pixel(s)", "px"), "")); }value: kcm.zoomMagnifierSettings.magnifierWidthonValueModified: kcm.zoomMagnifierSettings.magnifierWidth = valueKCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "MagnifierWidth"}}}Kirigami.FormEntry {visible: objectModel.visibletitle: i18nc("@label:spinbox", "Height:")contentItem: QQC2.SpinBox {id: magnifierHeightSpinBoxfrom: 100to: 2000stepSize: 10validator: IntValidator {bottom: Math.min(magnifierHeightSpinBox.from, magnifierHeightSpinBox.to)top: Math.max(magnifierHeightSpinBox.from, magnifierHeightSpinBox.to)}textFromValue: (value, locale) => { return i18ncp("short for pixel(s)", "%1 px", "%1 px", value); }valueFromText: (text, locale) => { return Number.fromLocaleString(locale, text.replace(i18nc("short for pixel(s)", "px"), "")); }value: kcm.zoomMagnifierSettings.magnifierHeightonValueModified: kcm.zoomMagnifierSettings.magnifierHeight = valueKCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "MagnifierHeight"}}}}Kirigami.FormGroup {Kirigami.FormEntry {title: i18nc("@label, followed by 'full screen' or 'magnify region'", "Zoom:")contentItem: QQC2.RadioButton {id: zoomRadioButtonQQC2.ButtonGroup.group: effectGrouptext: i18nc("@option:check, enable zoom effect, following 'Zoom:'", "Full screen")checked: kcm.zoomMagnifierSettings.zoomonToggled: { kcm.zoomMagnifierSettings.zoom = true; kcm.zoomMagnifierSettings.magnifier = false; }QQC2.ButtonGroup { id: effectGroup }KCM.SettingHighlighter { highlight: !kcm.zoomMagnifierSettings.zoom }}}Kirigami.FormEntry {contentItem: QQC2.RadioButton {id: magnifierRadioButtonQQC2.ButtonGroup.group: effectGrouptext: i18nc("@option:check, enable magnify effect, following 'Zoom:'", "Magnify region")checked: kcm.zoomMagnifierSettings.magnifieronToggled: { kcm.zoomMagnifierSettings.zoom = false; kcm.zoomMagnifierSettings.magnifier = true; }KCM.SettingHighlighter { highlight: !kcm.zoomMagnifierSettings.zoom }}}Kirigami.FormEntry {contentItem: QQC2.RadioButton {id: noneRadioButtonQQC2.ButtonGroup.group: effectGrouptext: i18nc("@option:check, disable zoom/magnify effect", "Disabled")checked: !(kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier)onToggled: { kcm.zoomMagnifierSettings.zoom = false; kcm.zoomMagnifierSettings.magnifier = false; }KCM.SettingHighlighter { highlight: !kcm.zoomMagnifierSettings.zoom }}}Kirigami.FormSeparator { visible: kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier}Repeater {model: FullScreenZoomSettingsModel {}}Repeater {model: MagnifierZoomSettingsModel {}}Kirigami.FormSeparator {}Kirigami.FormEntry {title: i18nc("@label:spinbox", "Zoom factor:")contentItem: QQC2.SpinBox {id: sharedZoomFactorSpinBoxfrom: toInt(1.05)to: toInt(4)stepSize: toInt(0.05)validator: IntValidator {bottom: Math.min(sharedZoomFactorSpinBox.from, sharedZoomFactorSpinBox.to)top: Math.max(sharedZoomFactorSpinBox.from, sharedZoomFactorSpinBox.to)}textFromValue: (value, locale) => fromInt(value).toLocaleString(locale, 'f', 2)valueFromText: (text, locale) => Math.round(toInt(Number.fromLocaleString(locale, text)))value: toInt(kcm.zoomMagnifierSettings.sharedZoomFactor)onValueModified: kcm.zoomMagnifierSettings.sharedZoomFactor = fromInt(value)function toInt(value: double) : int {return value * 20;}function fromInt(value: int) : double {return value / 20;}KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "SharedZoomFactor"extraEnabledConditions: kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier}}}}Kirigami.FormGroup {Kirigami.FormEntry {title: i18nc("@label", "Scroll gesture modifier keys:")subtitle: i18nc("@label Hint for scroll gestures", "Scroll while modifier keys are pressed to zoom")contentItem: KQuickControls.KeySequenceItem {id: zoomPointerAxisGestureModifiersBoxenabled: kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifierkeySequence: kcm.zoomMagnifierSettings.zoomPointerAxisGestureModifiersonKeySequenceModified: kcm.zoomMagnifierSettings.zoomPointerAxisGestureModifiers = keySequencepatterns: KQuickControls.ShortcutPattern.ModifiermultiKeyShortcutsAllowed: falseConnections {target: kcm.zoomMagnifierSettings// We have to do this because keySequence binding is brokenfunction onZoomPointerAxisGestureModifiersChanged() {zoomPointerAxisGestureModifiersBox.keySequence = kcm.zoomMagnifierSettings.zoomPointerAxisGestureModifiers;}}KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomPointerAxisGestureModifiers"}}}Kirigami.FormSeparator {}Kirigami.FormAction {enabled: action.enabledaction: QQC2.Action {enabled: (kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier)text: i18nc("@action:button", "Configure Shortcutsβ¦")icon.name: "preferences-desktop-keyboard-shortcut"onTriggered: kcm.configureZoomMagnifyShortcuts()}}}}