/*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.FormLayout {id: pageLayoutQQC2.RadioButton {id: zoomRadioButtonQQC2.ButtonGroup.group: effectGroupKirigami.FormData.label: i18nc("@label, followed by 'full screen' or 'magnify region'", "Zoom:")text: 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 }}RowLayout {Layout.fillWidth: truespacing: 0Item {// Provide indentation for child FormLayoutimplicitWidth: Application.layoutDirection === Qt.RightToLeft ? magnifierRadioButton.contentItem.rightPadding : magnifierRadioButton.contentItem.leftPadding}Kirigami.FormLayout {id: zoomLayouttwinFormLayouts: magnifierLayoutwideMode: pageLayout.wideModeenabled: kcm.zoomMagnifierSettings.zoomQQC2.SpinBox {id: zoomPixelGridZoomSpinBoxKirigami.FormData.label: i18nc("@label:spinbox", "Show pixel grid at zoom level:")from: 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"}}QQC2.ComboBox {Kirigami.FormData.label: i18nc("@label:listbox", "Pointer appearance:")model: [i18nc("@item:inlistbox", "Scale"), i18nc("@item:inlistbox", "Keep"), i18nc("@item:inlistbox", "Hide")]currentIndex: kcm.zoomMagnifierSettings.zoomMousePointeronActivated: (index) => kcm.zoomMagnifierSettings.zoomMousePointer = indexLayout.preferredWidth: Kirigami.Units.gridUnit * 15KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomMousePointer"}}Component {id: mouseTrackingItemDelegateQQC2.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}}}QQC2.ComboBox {Kirigami.FormData.label: i18nc("@label:listbox", "Pointer tracking:")delegate: mouseTrackingItemDelegatemodel: [{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"}}QQC2.CheckBox {text: i18nc("@option:check", "Enable focus tracking")checked: kcm.zoomMagnifierSettings.zoomEnableFocusTrackingonCheckedChanged: kcm.zoomMagnifierSettings.zoomEnableFocusTracking = checkedvisible: KWindowSystem.isPlatformX11KCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomEnableFocusTracking"}}QQC2.CheckBox {text: i18nc("@option:check", "Enable text caret tracking")checked: kcm.zoomMagnifierSettings.zoomEnableTextCaretTrackingonCheckedChanged: kcm.zoomMagnifierSettings.zoomEnableTextCaretTracking = checkedKCM.SettingStateBinding {configObject: kcm.zoomMagnifierSettingssettingName: "ZoomEnableTextCaretTracking"}}}}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 }}RowLayout {Layout.fillWidth: truespacing: 0Item {// Provide indentation for child FormLayoutimplicitWidth: Application.layoutDirection === Qt.RightToLeft ? magnifierRadioButton.contentItem.rightPadding : magnifierRadioButton.contentItem.leftPadding}Kirigami.FormLayout {id: magnifierLayouttwinFormLayouts: zoomLayoutwideMode: pageLayout.wideModeenabled: kcm.zoomMagnifierSettings.magnifierQQC2.SpinBox {id: magnifierWidthSpinBoxKirigami.FormData.label: i18nc("@label:spinbox", "Width:")from: 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"}}QQC2.SpinBox {id: magnifierHeightSpinBoxKirigami.FormData.label: i18nc("@label:spinbox", "Height:")from: 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"}}}}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 }}Item {Kirigami.FormData.isSection: true}QQC2.SpinBox {id: sharedZoomFactorSpinBoxKirigami.FormData.label: i18nc("@label:spinbox", "Zoom factor:")from: 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}}RowLayout {Kirigami.FormData.label: i18nc("@label", "Scroll gesture modifier keys:")spacing: Kirigami.Units.smallSpacingItem {// For some reason, here setting enabled directly on// KeySequenceItem does not work, so we wrap itenabled: !kcm.isPlatformX11 && (kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier)implicitWidth: zoomPointerAxisGestureModifiersBox.implicitWidthimplicitHeight: zoomPointerAxisGestureModifiersBox.implicitHeightKQuickControls.KeySequenceItem {id: zoomPointerAxisGestureModifiersBoxkeySequence: 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.ContextualHelpButton {visible: kcm.isPlatformX11toolTipText: i18nc("@info:tooltip, indicates feature unavailable on X11", "Zoom scroll gestures are only available on Wayland.")}}QQC2.Label {enabled: !kcm.isPlatformX11 && zoomPointerAxisGestureModifiersBox.keySequence != ""text: i18nc("@label Hint for scroll gestures", "Scroll while modifier keys are pressed to zoom")textFormat: Text.PlainTextwrapMode: Text.Wrapfont: Kirigami.Theme.smallFont}Item {Kirigami.FormData.isSection: true}QQC2.Button {text: i18nc("@action:button", "Configure Shortcutsβ¦")icon.name: "preferences-desktop-keyboard-shortcut"enabled: (kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier)onClicked: kcm.configureZoomMagnifyShortcuts()}QQC2.Label {enabled: (kcm.zoomMagnifierSettings.zoom || kcm.zoomMagnifierSettings.magnifier)text: i18nc("@label Hint for zoom/magnify effect usage", "Use shortcuts to control zoom")textFormat: Text.PlainTextwrapMode: Text.Wrapfont: Kirigami.Theme.smallFont}}