Warning, /plasma/kscreen/kcm/ui/OutputPanel.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0003
0004 SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 import QtCore
0007 import QtQuick 2.15
0008 import QtQuick.Layouts 1.15
0009 import QtQuick.Controls 2.15 as QQC2
0010 import QtQuick.Dialogs
0011 import org.kde.kirigami 2.20 as Kirigami
0012 import org.kde.kitemmodels 1.0
0013
0014 import org.kde.kcmutils as KCM
0015 import org.kde.private.kcm.kscreen 1.0 as KScreen
0016
0017 Kirigami.FormLayout {
0018 id: root
0019
0020 property KSortFilterProxyModel enabledOutputs
0021 property var element: model
0022
0023 signal reorder()
0024
0025 QQC2.CheckBox {
0026 text: i18n("Enabled")
0027 checked: element.enabled
0028 onToggled: element.enabled = checked
0029 visible: kcm.multipleScreensAvailable
0030 }
0031
0032 RowLayout {
0033 visible: kcm.primaryOutputSupported && root.enabledOutputs.count >= 2
0034
0035 QQC2.Button {
0036 visible: root.enabledOutputs.count >= 3
0037 text: i18n("Change Screen Priorities…")
0038 icon.name: "document-edit"
0039 onClicked: root.reorder();
0040 }
0041
0042 QQC2.RadioButton {
0043 visible: root.enabledOutputs.count === 2
0044 text: i18n("Primary")
0045 checked: element.priority === 1
0046 onToggled: element.priority = 1
0047 }
0048
0049 KCM.ContextualHelpButton {
0050 toolTipText: xi18nc("@info", "This determines which screen your main desktop appears on, along with any Plasma Panels in it. Some older games also use this setting to decide which screen to appear on.<nl/><nl/>It has no effect on what screen notifications or other windows appear on.")
0051 }
0052 }
0053
0054 RowLayout {
0055 Kirigami.FormData.label: i18n("Resolution:")
0056
0057 QQC2.ComboBox {
0058 id: resolutionCombobox
0059 Layout.minimumWidth: Kirigami.Units.gridUnit * 11
0060 visible: count > 1
0061 model: element.resolutions
0062 onActivated: element.resolutionIndex = currentIndex;
0063 Component.onCompleted: currentIndex = Qt.binding(function() {return element.resolutionIndex});
0064 }
0065 // When the combobox is has only one item, it's basically non-interactive
0066 // and is serving purely in a descriptive role, so make this explicit by
0067 // using a label instead
0068 QQC2.Label {
0069 id: singleResolutionLabel
0070 visible: resolutionCombobox.count <= 1
0071 text: element.resolutions[0] || ""
0072 }
0073 KCM.ContextualHelpButton {
0074 visible: resolutionCombobox.count <= 1
0075 toolTipText: xi18nc("@info", ""%1" is the only resolution supported by this display.", singleResolutionLabel.text)
0076 }
0077 }
0078
0079 RowLayout {
0080 Layout.fillWidth: true
0081 // Set the same limit as the device ComboBox
0082 Layout.maximumWidth: Kirigami.Units.gridUnit * 16
0083
0084 visible: kcm.perOutputScaling
0085 Kirigami.FormData.label: i18n("Scale:")
0086
0087 QQC2.Slider {
0088 id: scaleSlider
0089
0090 Layout.fillWidth: true
0091 from: 0.5
0092 to: 3
0093 stepSize: 0.25
0094 live: true
0095 value: element.scale
0096 onMoved: element.scale = value
0097 }
0098 QQC2.SpinBox {
0099 id: spinbox
0100 // Because QQC2 SpinBox doesn't natively support decimal step
0101 // sizes: https://bugreports.qt.io/browse/QTBUG-67349
0102 readonly property real factor: 20.0
0103 readonly property real realValue: value / factor
0104
0105 from : 0.5 * factor
0106 to : 3.0 * factor
0107 stepSize: 1
0108 value: element.scale * factor
0109 validator: DoubleValidator {
0110 bottom: Math.min(spinbox.from, spinbox.to) * spinbox.factor
0111 top: Math.max(spinbox.from, spinbox.to) * spinbox.factor
0112 }
0113 textFromValue: (value, locale) =>
0114 i18nc("Global scale factor expressed in percentage form", "%1%",
0115 parseFloat(value * 1.0 / factor * 100.0))
0116 valueFromText: (text, locale) =>
0117 Number.fromLocaleString(locale, text.replace("%", "")) * factor / 100.0
0118
0119 onValueModified: element.scale = realValue
0120 }
0121 }
0122
0123 Orientation {}
0124
0125 RowLayout {
0126 Kirigami.FormData.label: i18n("Refresh rate:")
0127
0128 QQC2.ComboBox {
0129 id: refreshRateCombobox
0130 Layout.minimumWidth: Kirigami.Units.gridUnit * 11
0131 visible: count > 1
0132 model: element.refreshRates
0133 onActivated: element.refreshRateIndex = currentIndex;
0134 Component.onCompleted: currentIndex = Qt.binding(function() {return element.refreshRateIndex});
0135 }
0136 // When the combobox is has only one item, it's basically non-interactive
0137 // and is serving purely in a descriptive role, so make this explicit by
0138 // using a label instead
0139 QQC2.Label {
0140 id: singleRefreshRateLabel
0141 visible: refreshRateCombobox.count <= 1
0142 text: element.refreshRates[0] || ""
0143 }
0144 KCM.ContextualHelpButton {
0145 visible: refreshRateCombobox.count <= 1
0146 toolTipText: i18n("\"%1\" is the only refresh rate supported by this display.", singleRefreshRateLabel.text)
0147 }
0148 }
0149
0150 QQC2.ComboBox {
0151 Kirigami.FormData.label: i18n("Adaptive sync:")
0152 Layout.minimumWidth: Kirigami.Units.gridUnit * 11
0153 model: [
0154 { label: i18n("Never"), value: KScreen.Output.VrrPolicy.Never },
0155 { label: i18n("Automatic"), value: KScreen.Output.VrrPolicy.Automatic },
0156 { label: i18n("Always"), value: KScreen.Output.VrrPolicy.Always },
0157 ]
0158 textRole: "label"
0159 valueRole: "value"
0160 visible: element.capabilities & KScreen.Output.Capability.Vrr
0161
0162 onActivated: element.vrrPolicy = currentValue;
0163 Component.onCompleted: currentIndex = indexOfValue(element.vrrPolicy);
0164 }
0165
0166 RowLayout {
0167 Kirigami.FormData.label: i18n("Overscan:")
0168 visible: element.capabilities & KScreen.Output.Capability.Overscan
0169
0170 QQC2.SpinBox {
0171 from: 0
0172 to: 100
0173 value: element.overscan
0174 onValueModified: element.overscan = value
0175 textFromValue: (value, locale) =>
0176 i18nc("Overscan expressed in percentage form", "%1%", value)
0177 valueFromText: (text, locale) =>
0178 Number.fromLocaleString(locale, text.replace("%", ""))
0179 }
0180
0181 KCM.ContextualHelpButton {
0182 toolTipText: xi18nc("@info", `Determines how much padding is put around the image sent to the display
0183 to compensate for part of the content being cut off around the edges.<nl/><nl/>
0184 This is sometimes needed when using a TV as a screen`)
0185 }
0186 }
0187
0188 RowLayout {
0189 Kirigami.FormData.label: i18n("RGB range:")
0190 visible: element.capabilities & KScreen.Output.Capability.RgbRange
0191
0192 QQC2.ComboBox {
0193 Layout.minimumWidth: Kirigami.Units.gridUnit * 11
0194 model: [
0195 { label: i18n("Automatic"), value: KScreen.Output.RgbRange.Automatic },
0196 { label: i18n("Full"), value: KScreen.Output.RgbRange.Full },
0197 { label: i18n("Limited"), value: KScreen.Output.RgbRange.Limited }
0198 ]
0199 textRole: "label"
0200 valueRole: "value"
0201
0202 onActivated: element.rgbRange = currentValue;
0203 Component.onCompleted: currentIndex = indexOfValue(element.rgbRange);
0204 }
0205
0206 KCM.ContextualHelpButton {
0207 toolTipText: xi18nc("@info", `Determines whether or not the range of possible color values needs to be limited for the display.
0208 This should only be changed if the colors on the screen look washed out.`)
0209 }
0210 }
0211
0212 RowLayout {
0213 Kirigami.FormData.label: i18nc("@label:textbox", "Color Profile:")
0214 visible: element.capabilities & KScreen.Output.Capability.IccProfile
0215 spacing: Kirigami.Units.smallSpacing
0216
0217 Kirigami.ActionTextField {
0218 id: iccProfileField
0219 onTextChanged: element.iccProfilePath = text
0220 onTextEdited: element.iccProfilePath = text
0221 placeholderText: i18nc("@info:placeholder", "Enter ICC profile path…")
0222 enabled: !element.hdr
0223
0224 rightActions: Kirigami.Action {
0225 icon.name: "edit-clear-symbolic"
0226 visible: iccProfileField.text !== ""
0227 onTriggered: {
0228 iccProfileField.text = ""
0229 }
0230 }
0231
0232 Component.onCompleted: text = element.iccProfilePath;
0233 }
0234
0235 QQC2.Button {
0236 icon.name: "document-open-symbolic"
0237 text: i18nc("@action:button", "Select ICC profile…")
0238 display: QQC2.AbstractButton.IconOnly
0239 onClicked: fileDialogComponent.incubateObject(root);
0240 enabled: !element.hdr
0241
0242 QQC2.ToolTip.visible: hovered
0243 QQC2.ToolTip.text: text
0244 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0245
0246 Accessible.role: Accessible.Button
0247 Accessible.name: text
0248 Accessible.description: i18n("Opens a file picker for the ICC profile")
0249 Accessible.onPressAction: onClicked();
0250 }
0251
0252 Component {
0253 id: fileDialogComponent
0254
0255 FileDialog {
0256 id: fileDialog
0257 title: i18nc("@title:window", "Select ICC Profile")
0258 currentFolder: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
0259 nameFilters: ["ICC profiles (*.icc *.icm)"]
0260
0261 onAccepted: {
0262 iccProfileField.text = urlToProfilePath(selectedFile);
0263 destroy();
0264 }
0265 onRejected: destroy();
0266 Component.onCompleted: open();
0267
0268 function urlToProfilePath(qmlUrl) {
0269 const url = new URL(qmlUrl);
0270 let path = decodeURIComponent(url.pathname);
0271 // Remove the leading slash from the url
0272 if (url.protocol === "file:" && path.charAt(1) === ':') {
0273 path = path.substring(1);
0274 }
0275 return path;
0276 }
0277 }
0278 }
0279
0280 KCM.ContextualHelpButton {
0281 visible: element.hdr
0282 toolTipText: i18nc("@info:tooltip", "ICC profiles aren't compatible with HDR yet")
0283 }
0284 }
0285
0286 RowLayout {
0287 Kirigami.FormData.label: i18nc("@label", "High Dynamic Range:")
0288 visible: (element.capabilities & KScreen.Output.Capability.HighDynamicRange) && (element.capabilities & KScreen.Output.Capability.WideColorGamut)
0289 spacing: Kirigami.Units.smallSpacing
0290
0291 QQC2.CheckBox {
0292 text: i18nc("@option:check", "Enable HDR")
0293 checked: element.hdr
0294 onToggled: element.hdr = checked
0295 }
0296
0297 KCM.ContextualHelpButton {
0298 toolTipText: i18nc("@info:tooltip", "HDR allows compatible applications to show brighter and more vivid colors. Note that this feature is still experimental")
0299 }
0300 }
0301
0302 RowLayout {
0303 Layout.fillWidth: true
0304 // Set the same limit as the device ComboBox
0305 Layout.maximumWidth: Kirigami.Units.gridUnit * 16
0306 spacing: Kirigami.Units.smallSpacing
0307
0308 visible: element.hdr
0309 Kirigami.FormData.label: i18nc("@label", "SDR Brightness:")
0310
0311 QQC2.Slider {
0312 Layout.fillWidth: true
0313 from: 50
0314 to: element.peakBrightness == 0 ? 500 : element.peakBrightness
0315 stepSize: 50
0316 live: true
0317 value: element.sdrBrightness
0318 onMoved: element.sdrBrightness = value
0319 }
0320 QQC2.SpinBox {
0321 from : 50
0322 to : element.peakBrightness == 0 ? 500 : element.peakBrightness
0323 stepSize: 10
0324 value: element.sdrBrightness
0325 onValueModified: element.sdrBrightness = value
0326 }
0327 KCM.ContextualHelpButton {
0328 toolTipText: i18nc("@info:tooltip", "Sets the brightness of non-HDR content on the screen, in nits")
0329 }
0330 }
0331
0332 RowLayout {
0333 Layout.fillWidth: true
0334 // Set the same limit as the device ComboBox
0335 Layout.maximumWidth: Kirigami.Units.gridUnit * 16
0336 spacing: Kirigami.Units.smallSpacing
0337
0338 visible: element.hdr
0339 Kirigami.FormData.label: i18nc("@label", "SDR Color Intensity:")
0340
0341 QQC2.Slider {
0342 Layout.fillWidth: true
0343 from: 0
0344 to: 100
0345 stepSize: 10
0346 live: true
0347 value: element.sdrGamutWideness * 100
0348 onMoved: element.sdrGamutWideness = value / 100.0
0349 }
0350 QQC2.SpinBox {
0351 // Because QQC2 SpinBox doesn't natively support decimal step
0352 // sizes: https://bugreports.qt.io/browse/QTBUG-67349
0353 readonly property real factor: 20.0
0354 readonly property real realValue: value / factor
0355
0356 from : 0
0357 to : 1.0 * factor
0358 stepSize: 1
0359 value: element.sdrGamutWideness * factor
0360 validator: DoubleValidator {
0361 bottom: Math.min(spinbox.from, spinbox.to) * spinbox.factor
0362 top: Math.max(spinbox.from, spinbox.to) * spinbox.factor
0363 }
0364 textFromValue: (value, locale) =>
0365 i18nc("Color intensity factor expressed in percentage form", "%1%",
0366 parseFloat(value * 1.0 / factor * 100.0))
0367 valueFromText: (text, locale) =>
0368 Number.fromLocaleString(locale, text.replace("%", "")) * factor / 100.0
0369
0370 onValueModified: element.sdrGamutWideness = realValue
0371 }
0372 KCM.ContextualHelpButton {
0373 toolTipText: i18nc("@info:tooltip", "Increases the intensity of non-HDR content on the screen")
0374 }
0375 }
0376
0377 QQC2.ComboBox {
0378 Kirigami.FormData.label: i18n("Replica of:")
0379 Layout.minimumWidth: Kirigami.Units.gridUnit * 11
0380 model: element.replicationSourceModel
0381 visible: kcm.outputReplicationSupported && kcm.multipleScreensAvailable
0382
0383 onModelChanged: enabled = (count > 1);
0384 onCountChanged: enabled = (count > 1);
0385
0386 Component.onCompleted: currentIndex = element.replicationSourceIndex;
0387 onActivated: element.replicationSourceIndex = currentIndex;
0388 }
0389 }