diff --git a/kcms/desktoptheme/package/contents/ui/main.qml b/kcms/desktoptheme/package/contents/ui/main.qml index e08a490af..4353a2f91 100644 --- a/kcms/desktoptheme/package/contents/ui/main.qml +++ b/kcms/desktoptheme/package/contents/ui/main.qml @@ -1,242 +1,236 @@ /* Copyright (c) 2014 Marco Martin Copyright (c) 2016 David Rosca Copyright (c) 2018 Kai Uwe Broulik Copyright (c) 2019 Kevin Ottens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.0 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami import org.kde.newstuff 1.62 as NewStuff -import org.kde.kcm 1.3 as KCM +import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.desktoptheme 1.0 as Private KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you choose the Plasma style.") view.model: kcm.filteredModel view.currentIndex: kcm.filteredModel.selectedThemeIndex - Binding { + Binding { target: kcm.filteredModel property: "query" value: searchField.text } Binding { target: kcm.filteredModel property: "filter" value: filterCombo.model[filterCombo.currentIndex].filter } - KCM.SettingStateBinding { - target: parent - configObject: kcm.desktopThemeSettings - itemName: "name" - extraEnabledPredicate: !kcm.downloadingFile - indicatorAsOverlay: true - } + enabled: !kcm.downloadingFile && !kcm.desktopThemeSettings.isImmutable("name") DropArea { anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: kcm.installThemeFromFile(drop.urls[0]) } header: RowLayout { Layout.fillWidth: true QtControls.TextField { id: searchField Layout.fillWidth: true placeholderText: i18n("Search...") leftPadding: LayoutMirroring.enabled ? clearButton.width : undefined rightPadding: LayoutMirroring.enabled ? undefined : clearButton.width // this could be useful as a component MouseArea { id: clearButton anchors { top: parent.top topMargin: parent.topPadding right: parent.right // the TextField's padding is taking into account the clear button's size // so we just use the opposite one for positioning the clear button rightMargin: LayoutMirroring.enabled ? parent.rightPadding: parent.leftPadding bottom: parent.bottom bottomMargin: parent.bottomPadding } width: height opacity: searchField.length > 0 ? 1 : 0 onClicked: searchField.clear() Kirigami.Icon { anchors.fill: parent active: parent.pressed source: "edit-clear-locationbar-" + (LayoutMirroring.enabled ? "ltr" : "rtl") } Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } } } QtControls.ComboBox { id: filterCombo textRole: "text" model: [ {text: i18n("All Themes"), filter: Private.FilterProxyModel.AllThemes}, {text: i18n("Light Themes"), filter: Private.FilterProxyModel.LightThemes}, {text: i18n("Dark Themes"), filter: Private.FilterProxyModel.DarkThemes}, {text: i18n("Color scheme compatible"), filter: Private.FilterProxyModel.ThemesFollowingColors} ] // HACK QQC2 doesn't support icons, so we just tamper with the desktop style ComboBox's background // and inject a nice little filter icon. Component.onCompleted: { if (!background || !background.hasOwnProperty("properties")) { // not a KQuickStyleItem return; } var props = background.properties || {}; background.properties = Qt.binding(function() { var newProps = props; newProps.currentIcon = "view-filter"; newProps.iconColor = Kirigami.Theme.textColor; return newProps; }); } } } view.delegate: KCM.GridDelegate { id: delegate text: model.display subtitle: model.colorType == Private.ThemesModel.FollowsColorTheme && view.model.filter != Private.FilterProxyModel.ThemesFollowingColors ? i18n("Follows color scheme") : "" toolTip: model.description || model.display opacity: model.pendingDeletion ? 0.3 : 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } thumbnailAvailable: true thumbnail: ThemePreview { id: preview anchors.fill: parent themeName: model.pluginName } actions: [ Kirigami.Action { iconName: "document-edit" tooltip: i18n("Edit Theme...") enabled: !model.pendingDeletion visible: kcm.canEditThemes onTriggered: kcm.editTheme(model.pluginName) }, Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Remove Theme") enabled: model.isLocal visible: !model.pendingDeletion onTriggered: model.pendingDeletion = true; }, Kirigami.Action { iconName: "edit-undo" tooltip: i18n("Restore Theme") visible: model.pendingDeletion onTriggered: model.pendingDeletion = false; } ] onClicked: { kcm.desktopThemeSettings.name = model.pluginName; view.forceActiveFocus(); } } footer: ColumnLayout { Kirigami.InlineMessage { id: infoLabel Layout.fillWidth: true showCloseButton: true Connections { target: kcm onShowSuccessMessage: { infoLabel.type = Kirigami.MessageType.Positive; infoLabel.text = message; infoLabel.visible = true; } onShowErrorMessage: { infoLabel.type = Kirigami.MessageType.Error; infoLabel.text = message; infoLabel.visible = true; } } } RowLayout { Layout.alignment: Qt.AlignRight QtControls.Button { text: i18n("Install from File...") icon.name: "document-import" onClicked: fileDialogLoader.active = true; } NewStuff.Button { id: newStuffButton text: i18n("Get New Plasma Styles...") configFile: "plasma-themes.knsrc" viewMode: NewStuff.Page.ViewMode.Preview onChangedEntriesChanged: kcm.load(); } } } Loader { id: fileDialogLoader active: false sourceComponent: FileDialog { title: i18n("Open Theme") folder: shortcuts.home nameFilters: [ i18n("Theme Files (*.zip *.tar.gz *.tar.bz2)") ] Component.onCompleted: open() onAccepted: { kcm.installThemeFromFile(fileUrls[0]) fileDialogLoader.active = false } onRejected: { fileDialogLoader.active = false } } } } diff --git a/kcms/icons/package/contents/ui/IconSizePopup.qml b/kcms/icons/package/contents/ui/IconSizePopup.qml index 0d8827d14..d26a227a0 100644 --- a/kcms/icons/package/contents/ui/IconSizePopup.qml +++ b/kcms/icons/package/contents/ui/IconSizePopup.qml @@ -1,175 +1,168 @@ /* * Copyright 2018 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.7 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kcm 1.3 as KCM QtControls.Popup { id: iconSizePopup width: 400 modal: true onOpened: { // can we do this automatically with "focus: true" somewhere? iconTypeList.forceActiveFocus(); } onVisibleChanged: { if (visible) { iconSizeSlider.sizes = kcm.availableIconSizes(iconTypeList.currentIndex); iconSizeSlider.updateSizes() } } Connections { target: iconTypeList onCurrentIndexChanged: { iconSizeSlider.sizes = kcm.availableIconSizes(iconTypeList.currentIndex); } } RowLayout { anchors.fill: parent ColumnLayout { id: iconSizeColumn Layout.fillWidth: true QtControls.ItemDelegate { // purely for metrics... id: measureDelegate visible: false } QtControls.ScrollView { id: iconTypeScroll Layout.fillWidth: true Layout.fillHeight: true Layout.preferredHeight: iconTypeList.count * measureDelegate.height + 4 activeFocusOnTab: false Component.onCompleted: iconTypeScroll.background.visible = true; ListView { id: iconTypeList activeFocusOnTab: true keyNavigationEnabled: true keyNavigationWraps: true highlightMoveDuration: 0 model: kcm.iconSizeCategoryModel currentIndex: 0 // Initialize with the first item Keys.onLeftPressed: { LayoutMirroring.enabled ? iconSizeSlider.increase() : iconSizeSlider.decrease() iconSizeSlider.moved(); } Keys.onRightPressed: { LayoutMirroring.enabled ? iconSizeSlider.decrease() : iconSizeSlider.increase() iconSizeSlider.moved(); } delegate: QtControls.ItemDelegate { width: ListView.view.width highlighted: ListView.isCurrentItem text: model.display readonly property string configKey: model.configKey onClicked: { ListView.view.currentIndex = index; ListView.view.forceActiveFocus(); } } } } QtControls.Slider { id: iconSizeSlider property var sizes: kcm.availableIconSizes(iconTypeList.currentIndex) Layout.fillWidth: true from: 0 to: sizes.length - 1 stepSize: 1.0 snapMode: QtControls.Slider.SnapAlways - - KCM.SettingStateBinding { - target: parent - configObject: kcm.iconsSettings - itemName: iconTypeList.currentItem.configKey - extraEnabledPredicate: parent.sizes.length > 0 - } + enabled: sizes.length > 0 && !kcm.iconsSettings.isImmutable(iconTypeList.currentItem.configKey) onMoved: { kcm.iconsSettings[iconTypeList.currentItem.configKey] = iconSizeSlider.sizes[iconSizeSlider.value] || 0 } function updateSizes() { // since the icon sizes are queried using invokables, always force an update when opening // in case the user clicked Default or something value = Qt.binding(function() { var iconSize = kcm.iconsSettings[iconTypeList.currentItem.configKey] // I have no idea what this code does but it works and is just copied from the old KCM var index = -1; var delta = 1000; for (var i = 0, length = sizes.length; i < length; ++i) { var dw = Math.abs(iconSize - sizes[i]); if (dw < delta) { delta = dw; index = i; } } return index; }); } } } ColumnLayout { Layout.fillHeight: true Layout.minimumWidth: Math.round(parent.width / 2) Layout.maximumWidth: Math.round(parent.width / 2) Item { Layout.fillWidth: true Layout.fillHeight: true clip: true Kirigami.Icon { anchors.centerIn: parent width: kcm.iconsSettings[iconTypeList.currentItem.configKey] height: width source: "folder" } } QtControls.Label { id: iconSizeLabel Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter text: kcm.iconsSettings[iconTypeList.currentItem.configKey] } } } } diff --git a/kcms/icons/package/contents/ui/main.qml b/kcms/icons/package/contents/ui/main.qml index ba10b8b4f..4498f9ae7 100644 --- a/kcms/icons/package/contents/ui/main.qml +++ b/kcms/icons/package/contents/ui/main.qml @@ -1,298 +1,290 @@ /* * Copyright 2018 Kai Uwe Broulik * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.7 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.0 as QtDialogs import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami import org.kde.kquickcontrolsaddons 2.0 as KQCAddons import org.kde.newstuff 1.62 as NewStuff -import org.kde.kcm 1.3 as KCM +import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.icons 1.0 as Private KCM.GridViewKCM { - id: root KCM.ConfigModule.quickHelp: i18n("This module allows you to choose the icons for your desktop.") view.model: kcm.iconsModel view.currentIndex: kcm.pluginIndex(kcm.iconsSettings.theme) enabled: !kcm.downloadingFile - - KCM.SettingStateBinding { - target: view - configObject: kcm.iconsSettings - itemName: "Theme" - indicatorAsOverlay: true - } + view.enabled: !kcm.iconsSettings.isImmutable("Theme") DropArea { - enabled: view.enabled + enabled: !kcm.iconsSettings.isImmutable("Theme") anchors.fill: parent onEntered: { if (!drag.hasUrls) { drag.accepted = false; } } onDropped: kcm.installThemeFromFile(drop.urls[0]) } view.delegate: KCM.GridDelegate { id: delegate text: model.display toolTip: model.description thumbnailAvailable: typeof thumbFlow.previews === "undefined" || thumbFlow.previews.length > 0 thumbnail: MouseArea { id: thumbArea anchors.fill: parent acceptedButtons: Qt.NoButton hoverEnabled: true clip: thumbFlow.y < 0 opacity: model.pendingDeletion ? 0.3 : 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } } Timer { interval: 1000 repeat: true running: thumbArea.containsMouse onRunningChanged: { if (!running) { thumbFlow.currentPage = 0; } } onTriggered: { if (!thumbFlow.allPreviesLoaded) { thumbFlow.loadPreviews(-1 /*no limit*/); thumbFlow.allPreviesLoaded = true; } ++thumbFlow.currentPage; if (thumbFlow.currentPage >= thumbFlow.pageCount) { stop(); } } } Flow { id: thumbFlow // undefined is "didn't load preview yet" // empty array is "no preview available" property var previews // initially we only load 6 and when the animation starts we'll load the rest property bool allPreviesLoaded: false property int currentPage readonly property int pageCount: Math.ceil(thumbRepeater.count / (thumbFlow.columns * thumbFlow.rows)) readonly property int iconWidth: Math.floor(thumbArea.width / thumbFlow.columns) readonly property int iconHeight: Math.floor(thumbArea.height / thumbFlow.rows) readonly property int columns: 3 readonly property int rows: 2 function loadPreviews(limit) { previews = kcm.previewIcons(model.themeName, Math.min(thumbFlow.iconWidth, thumbFlow.iconHeight), Screen.devicePixelRatio, limit); } width: parent.width y: -currentPage * iconHeight * rows Behavior on y { NumberAnimation { duration: Kirigami.Units.longDuration } } Repeater { id: thumbRepeater model: thumbFlow.previews Item { width: thumbFlow.iconWidth height: thumbFlow.iconHeight KQCAddons.QPixmapItem { anchors.centerIn: parent width: Math.min(parent.width, nativeWidth) height: Math.min(parent.height, nativeHeight) // load on demand and avoid leaking a tiny corner of the icon pixmap: thumbFlow.y < 0 || index < (thumbFlow.columns * thumbFlow.rows) ? modelData : undefined smooth: true fillMode: KQCAddons.QPixmapItem.PreserveAspectFit } } } Component.onCompleted: { // avoid reloading it when icon sizes or dpr changes on startup Qt.callLater(function() { // We show 6 icons initially (3x2 grid), only load those thumbFlow.loadPreviews(6 /*limit*/); }); } } } actions: [ Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Remove Icon Theme") enabled: model.removable visible: !model.pendingDeletion onTriggered: model.pendingDeletion = true }, Kirigami.Action { iconName: "edit-undo" tooltip: i18n("Restore Icon Theme") visible: model.pendingDeletion onTriggered: model.pendingDeletion = false } ] onClicked: { if (!model.pendingDeletion) { kcm.iconsSettings.theme = model.themeName; } view.forceActiveFocus(); } } footer: ColumnLayout { Kirigami.InlineMessage { id: infoLabel Layout.fillWidth: true showCloseButton: true Connections { target: kcm onShowSuccessMessage: { infoLabel.type = Kirigami.MessageType.Positive; infoLabel.text = message; infoLabel.visible = true; } onShowErrorMessage: { infoLabel.type = Kirigami.MessageType.Error; infoLabel.text = message; infoLabel.visible = true; } } } RowLayout { id: progressRow visible: false QtControls.BusyIndicator { id: progressBusy } QtControls.Label { id: progressLabel Layout.fillWidth: true textFormat: Text.PlainText wrapMode: Text.WordWrap } Connections { target: kcm onShowProgress: { progressLabel.text = message; progressBusy.running = true; progressRow.visible = true; } onHideProgress: { progressBusy.running = false; progressRow.visible = false; } } } RowLayout { Layout.fillWidth: true QtControls.Button { id: iconSizesButton text: i18n("Configure Icon Sizes") icon.name: "transform-scale" // proper icon? checkable: true checked: iconSizePopupLoader.item && iconSizePopupLoader.item.opened onClicked: { iconSizePopupLoader.active = true; iconSizePopupLoader.item.open(); } } Item { Layout.fillWidth: true } QtControls.Button { + enabled: !kcm.iconsSettings.isImmutable("Theme") id: installFromFileButton - enabled: root.view.enabled text: i18n("Install from File...") icon.name: "document-import" onClicked: fileDialogLoader.active = true } NewStuff.Button { id: newStuffButton - enabled: root.view.enabled text: i18n("Get New Icons...") configFile: "icons.knsrc" viewMode: NewStuff.Page.ViewMode.Preview onChangedEntriesChanged: kcm.ghnsEntriesChanged(newStuffButton.changedEntries); } } } Loader { id: iconSizePopupLoader active: false sourceComponent: IconSizePopup { parent: iconSizesButton y: -height } } Loader { id: fileDialogLoader active: false sourceComponent: QtDialogs.FileDialog { title: i18n("Open Theme") folder: shortcuts.home nameFilters: [ i18n("Theme Files (*.tar.gz *.tar.bz2)") ] Component.onCompleted: open() onAccepted: { kcm.installThemeFromFile(fileUrls[0]) fileDialogLoader.active = false } onRejected: { fileDialogLoader.active = false } } } } diff --git a/kcms/workspaceoptions/package/contents/ui/main.qml b/kcms/workspaceoptions/package/contents/ui/main.qml index f2452ddd1..79ceb05db 100644 --- a/kcms/workspaceoptions/package/contents/ui/main.qml +++ b/kcms/workspaceoptions/package/contents/ui/main.qml @@ -1,202 +1,177 @@ /* * Copyright 2018 Furkan Tokac * Copyright (C) 2019 Nate Graham * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.5 as QQC2 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.5 as Kirigami -import org.kde.kcm 1.3 as KCM +import org.kde.kcm 1.2 as KCM import org.kde.plasma.core 2.0 as PlasmaCore KCM.SimpleKCM { id: root implicitWidth: Kirigami.Units.gridUnit * 40 Kirigami.FormLayout { id: formLayout // Visual behavior settings QQC2.CheckBox { id: showToolTips Kirigami.FormData.label: i18n("Visual behavior:") text: i18n("Display informational tooltips on mouse hover") + enabled: !kcm.plasmaSettings.isImmutable("delay") checked: kcm.plasmaSettings.delay > 0 onCheckedChanged: { if (checked) { kcm.plasmaSettings.delay = 0.7 } else { kcm.plasmaSettings.delay = -1 } } - - KCM.SettingStateBinding { - target: parent - configObject: kcm.plasmaSettings - itemName: "delay" - } } QQC2.CheckBox { id: showVisualFeedback text: i18n("Display visual feedback for status changes") + enabled: !kcm.plasmaSettings.isImmutable("osdEnabled") checked: kcm.plasmaSettings.osdEnabled onCheckedChanged: kcm.plasmaSettings.osdEnabled = checked - - KCM.SettingStateBinding { - target: parent - configObject: kcm.plasmaSettings - itemName: "osdEnabled" - } } Item { Kirigami.FormData.isSection: false } // We want to show the slider in a logarithmic way. ie // move from 4x, 3x, 2x, 1x, 0.5x, 0.25x, 0.125x // 0 is a special case ColumnLayout { + enabled: !kcm.globalsSettings.isImmutable("animationDurationFactor") Kirigami.FormData.label: i18n("Animation speed:") Kirigami.FormData.buddyFor: slider QQC2.Slider { id: slider Layout.fillWidth: true from: -4 to: 4 stepSize: 0.5 snapMode: QQC2.Slider.SnapAlways onMoved: { if(value === to) { kcm.globalsSettings.animationDurationFactor = 0; } else { kcm.globalsSettings.animationDurationFactor = 1.0 / Math.pow(2, value); } } value: if (kcm.globalsSettings.animationDurationFactor === 0) { return slider.to; } else { return -(Math.log(kcm.globalsSettings.animationDurationFactor) / Math.log(2)); } - - KCM.SettingStateBinding { - target: parent - configObject: kcm.globalsSettings - itemName: "animationDurationFactor" - } } RowLayout { QQC2.Label { text: i18nc("Animation speed", "Slow") } Item { Layout.fillWidth: true } QQC2.Label { text: i18nc("Animation speed", "Instant") } } } Item { Kirigami.FormData.isSection: false } // Click behavior settings QQC2.ButtonGroup { id: singleClickGroup } QQC2.RadioButton { id: singleClick Kirigami.FormData.label: i18n("Click behavior:") text: i18n("Single-click to open files and folders") + enabled: !kcm.globalsSettings.isImmutable("singleClick") checked: kcm.globalsSettings.singleClick onToggled: kcm.globalsSettings.singleClick = true QQC2.ButtonGroup.group: singleClickGroup - - KCM.SettingStateBinding { - target: parent - configObject: kcm.globalsSettings - itemName: "singleClick" - } } QQC2.RadioButton { id: doubleClick text: i18n("Double-click to open files and folders") - enabled: singleClick.enabled + enabled: !kcm.globalsSettings.isImmutable("singleClick") checked: !kcm.globalsSettings.singleClick onToggled: kcm.globalsSettings.singleClick = false QQC2.ButtonGroup.group: singleClickGroup } QQC2.Label { Layout.fillWidth: true text: singleClick.checked ? i18n("Select by clicking on item's selection marker") : i18n("Select by single-clicking") elide: Text.ElideRight font.pointSize: theme.smallestFont.pointSize } Item { Kirigami.FormData.isSection: false } // scroll handle settings QQC2.ButtonGroup { id: scrollHandleBehaviorGroup } QQC2.RadioButton { id: scrollbarLeftClickNavigatesByPage Kirigami.FormData.label: i18n("Clicking in scrollbar track:") text: i18nc("@radio part of a complete sentence: 'Clicking in scrollbar track scrolls one page up or down'", "Scrolls one page up or down") + enabled: !kcm.globalsSettings.isImmutable("scrollbarLeftClickNavigatesByPage") checked: kcm.globalsSettings.scrollbarLeftClickNavigatesByPage onToggled: kcm.globalsSettings.scrollbarLeftClickNavigatesByPage = true QQC2.ButtonGroup.group: scrollHandleBehaviorGroup - - KCM.SettingStateBinding { - target: parent - configObject: kcm.globalsSettings - itemName: "scrollbarLeftClickNavigatesByPage" - } } QQC2.RadioButton { id: scrollBarLeftClickWarpsScrollHandle text: i18nc("@radio part of a complete sentence: 'Clicking in scrollbar track scrolls to the clicked location'", "Scrolls to the clicked location") - enabled: scrollbarLeftClickNavigatesByPage.enabled + enabled: !kcm.globalsSettings.isImmutable("scrollbarLeftClickNavigatesByPage") checked: !kcm.globalsSettings.scrollbarLeftClickNavigatesByPage onToggled: kcm.globalsSettings.scrollbarLeftClickNavigatesByPage = false QQC2.ButtonGroup.group: scrollHandleBehaviorGroup } // Don't show a label for what middle-clicking does when using the // "click to zoom the handle" behavior because Qt doesn't invert the // middle-click functionality when using this; see // https://bugreports.qt.io/browse/QTBUG-80728 QQC2.Label { Layout.fillWidth: true visible: scrollbarLeftClickNavigatesByPage.checked text: i18n("Middle-click to scroll to clicked location") elide: Text.ElideRight font.pointSize: theme.smallestFont.pointSize } } }