From ff194dc1a1cffd296652cd0f4cf21969d51c258d Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sun, 16 Apr 2023 19:08:28 +0200 Subject: [PATCH] refactor: modernize QML code to make it work with Qt 6 This cherry-picks several changes from KScreen to make KDisplay work with Qt 6. --- kcm/kcm.cpp | 14 +- kcm/kcm.h | 11 +- kcm/package/contents/ui/Orientation.qml | 46 +++-- kcm/package/contents/ui/Output.qml | 232 ++++++++++++------------ kcm/package/contents/ui/Screen.qml | 26 ++- kcm/package/contents/ui/main.qml | 160 ++++++++++++---- kcm/po/kcm_kdisplay.pot | 69 ++++--- 7 files changed, 334 insertions(+), 224 deletions(-) diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index b940766..255fa1a 100644 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -85,17 +85,7 @@ void KCMKDisplay::configReady(ConfigOperation* op) Q_EMIT outputRetentionChanged(); } -void KCMKDisplay::forceSave() -{ - doSave(true); -} - void KCMKDisplay::save() -{ - doSave(false); -} - -void KCMKDisplay::doSave(bool force) { if (!m_config) { Q_EMIT errorOnSave(); @@ -134,8 +124,8 @@ void KCMKDisplay::doSave(bool force) << (output->replication_source() == 0 ? "no" : "yes"); } - if (!atLeastOneEnabledOutput && !force) { - Q_EMIT dangerousSave(); + if (!atLeastOneEnabledOutput) { + Q_EMIT invalidConfig(InvalidConfigReason::NoEnabledOutputs); m_config->checkNeedsSave(); return; } diff --git a/kcm/kcm.h b/kcm/kcm.h index 2d6796e..5992a98 100644 --- a/kcm/kcm.h +++ b/kcm/kcm.h @@ -53,6 +53,12 @@ class KCMKDisplay : public KQuickManagedConfigModule Q_PROPERTY(bool tabletModeAvailable READ tabletModeAvailable NOTIFY tabletModeAvailableChanged) public: + enum InvalidConfigReason { + NoEnabledOutputs, + ConfigHasGaps, + }; + Q_ENUM(InvalidConfigReason) + KCMKDisplay(QObject* parent, const KPluginMetaData& data, const QVariantList& args); ~KCMKDisplay() override = default; @@ -84,9 +90,6 @@ class KCMKDisplay : public KQuickManagedConfigModule bool orientationSensorAvailable() const; bool tabletModeAvailable() const; - Q_INVOKABLE void forceSave(); - void doSave(bool force); - Q_SIGNALS: void backendReadyChanged(); void backendError(); @@ -102,7 +105,7 @@ class KCMKDisplay : public KQuickManagedConfigModule void autoRotationSupportedChanged(); void orientationSensorAvailableChanged(); void tabletModeAvailableChanged(); - void dangerousSave(); + void invalidConfig(InvalidConfigReason); void errorOnSave(); void globalScaleWritten(); void outputConnect(bool connected); diff --git a/kcm/package/contents/ui/Orientation.qml b/kcm/package/contents/ui/Orientation.qml index fc208d4..83be55a 100644 --- a/kcm/package/contents/ui/Orientation.qml +++ b/kcm/package/contents/ui/Orientation.qml @@ -14,14 +14,14 @@ 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.9 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.3 as Controls -import org.kde.kirigami 2.4 as Kirigami +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 +import org.kde.kirigami 2.20 as Kirigami ColumnLayout { Kirigami.FormData.label: i18n("Orientation:") - Kirigami.FormData.buddyFor: auto_rotate_switch + Kirigami.FormData.buddyFor: autoRotateColumn.visible ? autoRotateRadio : orientation spacing: Kirigami.Units.smallSpacing ColumnLayout { @@ -31,26 +31,38 @@ ColumnLayout { enabled: element.internal visible: kcm.autoRotationSupported && kcm.orientationSensorAvailable - Controls.Switch { - id: auto_rotate_switch - text: i18n("Auto") - checked: enabled && element.autoRotate - onToggled: element.autoRotate = checked + ColumnLayout { + QQC2.RadioButton { + id: autoRotateRadio + text: i18n("Automatic") + checked: autoRotateColumn.enabled && element.autoRotate + onToggled: element.autoRotate = true + } + + QQC2.CheckBox { + id: autoRotateOnlyInTabletMode + Layout.leftMargin: Kirigami.Units.gridUnit + + text: i18n("Only when in tablet mode") + enabled: autoRotateRadio.checked + checked: enabled && element.autoRotateOnlyInTabletMode + onToggled: element.autoRotateOnlyInTabletMode = checked + } } - Controls.Switch { - text: i18n("Only when in tablet mode.") - visible: auto_rotate_switch.checked - checked: element.autoRotateOnlyInTabletMode - onToggled: element.autoRotateOnlyInTabletMode = checked + QQC2.RadioButton { + id: manualRotateRadio + text: i18n("Manual") + checked: !element.autoRotate || !autoRotateColumn.enabled + onToggled: element.autoRotate = false } } RowLayout { id: orientation - visible: !auto_rotate_switch.checked || !kcm.autoRotationSupported + enabled: !element.autoRotate || !autoRotateColumn.enabled || !autoRotateColumn.visible - Controls.ButtonGroup { + QQC2.ButtonGroup { buttons: orientation.children } diff --git a/kcm/package/contents/ui/Output.qml b/kcm/package/contents/ui/Output.qml index b9e6124..ebf73c9 100644 --- a/kcm/package/contents/ui/Output.qml +++ b/kcm/package/contents/ui/Output.qml @@ -15,16 +15,15 @@ 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.12 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.3 as Controls -import QtGraphicalEffects 1.0 -import org.kde.kirigami 2.4 as Kirigami +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 +import org.kde.kirigami 2.20 as Kirigami Item { id: output - property bool isSelected: root.selectedOutput === model.index + readonly property bool isSelected: root.selectedOutput === model.index property size outputSize: model.size onIsSelectedChanged: { @@ -37,7 +36,7 @@ Item { function getAbsolutePosition(pos) { return Qt.point((pos.x - screen.xOffset) * screen.relativeFactor, - (pos.y - screen.yOffset) * screen.relativeFactor) ; + (pos.y - screen.yOffset) * screen.relativeFactor); } visible: model.enabled && model.replicationSourceIndex === 0 @@ -51,24 +50,44 @@ Item { width: model.size ? model.size.width / screen.relativeFactor : 1 height: model.size ? model.size.height / screen.relativeFactor : 1 - SystemPalette { - id: palette - } - Rectangle { id: outline - radius: 4 - color: palette.window - anchors.fill: parent + readonly property int orientationPanelWidth: 10 + readonly property real orientationPanelPosition: 1 - (orientationPanelWidth / outline.height) + + anchors.centerIn: parent + width: parent.width + height: parent.height + radius: Kirigami.Units.smallSpacing + + gradient: Gradient { + GradientStop { + position: 0.0 + color: Kirigami.Theme.alternateBackgroundColor + } + GradientStop { + // Create a hard cut. Can't use the same number otherwise it gets confused. + position: outline.orientationPanelPosition - Number.EPSILON + color: Kirigami.Theme.alternateBackgroundColor + } + GradientStop { + position: outline.orientationPanelPosition + color: outline.border.color + } + GradientStop { + position: 1.0 + color: outline.border.color + } + } border { - color: isSelected ? palette.highlight : palette.shadow + color: isSelected ? Kirigami.Theme.highlightColor : Kirigami.Theme.disabledTextColor width: 1 Behavior on color { PropertyAnimation { - duration: 150 + duration: Kirigami.Units.longDuration } } } @@ -76,16 +95,31 @@ Item { Item { anchors.fill: parent + // So we can show a grabby hand cursor when hovered over + HoverHandler { + cursorShape: kcm.outputModel && kcm.outputModel.rowCount() > 1 ? Qt.SizeAllCursor : undefined + } + z: 2 + } + + Item { + id: labelContainer + anchors { + fill: parent + margins: outline.border.width + } + // so the text is drawn above orientationPanelContainer + z: 1 ColumnLayout { anchors.centerIn: parent spacing: 0 width: parent.width Layout.maximumHeight: parent.height - Controls.Label { + QQC2.Label { Layout.fillWidth: true - Layout.margins: Kirigami.Units.smallSpacing + Layout.maximumHeight: labelContainer.height - resolutionLabel.implicitHeight text: model.display wrapMode: Text.Wrap @@ -93,17 +127,76 @@ Item { elide: Text.ElideRight } - Controls.Label { + QQC2.Label { + id: resolutionLabel Layout.fillWidth: true - Layout.bottomMargin: Kirigami.Units.smallSpacing text: "(" + model.size.width + "x" + model.size.height + ")" + wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight } } } + states: [ + State { + name: "transposed" + PropertyChanges { + target: outline + width: output.height + height: output.width + } + }, + + State { + name: "rot0" + when: model.rotation === 1 + PropertyChanges { + target: labelContainer + anchors.bottomMargin: outline.orientationPanelWidth + outline.border.width + } + }, + State { + name: "rot90" + extend: "transposed" + when: model.rotation === 2 + PropertyChanges { + target: outline + rotation: 90 + } + PropertyChanges { + target: labelContainer + anchors.leftMargin: outline.orientationPanelWidth + outline.border.width + } + }, + State { + name: "rot180" + when: model.rotation === 4 + PropertyChanges { + target: outline + rotation: 180 + } + PropertyChanges { + target: labelContainer + anchors.topMargin: outline.orientationPanelWidth + outline.border.width + } + }, + State { + name: "rot270" + extend: "transposed" + when: model.rotation === 8 + PropertyChanges { + target: outline + rotation: 270 + } + PropertyChanges { + target: labelContainer + anchors.rightMargin: outline.orientationPanelWidth + outline.border.width + } + } + ] + Rectangle { id: posLabel @@ -117,7 +210,7 @@ Item { (tapHandler.isLongPressed || dragHandler.active) ? 0.9 : 0.0 - color: palette.shadow + color: Kirigami.Theme.disabledTextColor Text { id: posLabelText @@ -131,12 +224,12 @@ Item { Behavior on opacity { PropertyAnimation { - duration: 100; + duration: Kirigami.Units.longDuration } } } - Controls.ToolButton { + QQC2.ToolButton { id: replicas property int selectedReplica: -1 @@ -150,7 +243,7 @@ Item { visible: model.replicasModel.length > 0 icon.name: "osd-duplicate" - Controls.ToolTip { + QQC2.ToolTip { text: i18n("Replicas") } @@ -163,79 +256,6 @@ Item { root.selectedOutput = model.replicasModel[index]; } } - - } - - Item { - id: orientationPanelContainer - - anchors.fill: output - visible: false - - Rectangle { - id: orientationPanel - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - - height: 10 - color: isSelected ? palette.highlight : palette.shadow - smooth: true - - Behavior on color { - PropertyAnimation { - duration: 150 - } - } - } - } - - states: [ - State { - name: "rot90" - when: model.rotation === 2 - PropertyChanges { - target: orientationPanel - height: undefined - width: 10 - } - AnchorChanges { - target: orientationPanel - anchors.right: undefined - anchors.top: orientationPanelContainer.top - } - }, - State { - name: "rot180" - when: model.rotation === 4 - AnchorChanges { - target: orientationPanel - anchors.top: orientationPanelContainer.top - anchors.bottom: undefined - } - }, - State { - name: "rot270" - when: model.rotation === 8 - PropertyChanges { - target: orientationPanel - height: undefined - width: 10 - } - AnchorChanges { - target: orientationPanel - anchors.left: undefined - anchors.top: orientationPanelContainer.top - } - } - ] - - OpacityMask { - anchors.fill: orientationPanelContainer - source: orientationPanelContainer - maskSource: outline } property point dragStartPosition @@ -243,14 +263,11 @@ Item { TapHandler { id: tapHandler property bool isLongPressed: false + gesturePolicy: TapHandler.WithinBounds - function bindSelectedOutput() { - root.selectedOutput - = Qt.binding(function() { return model.index; }); - } onPressedChanged: { if (pressed) { - bindSelectedOutput(); + root.selectedOutput = model.index; dragStartPosition = Qt.point(output.x, output.y) } else { isLongPressed = false; @@ -263,6 +280,7 @@ Item { id: dragHandler enabled: kcm.outputModel && kcm.outputModel.rowCount() > 1 acceptedButtons: Qt.LeftButton + grabPermissions: PointerHandler.CanTakeOverFromAnything | PointerHandler.TakeOverForbidden target: null onTranslationChanged: { @@ -271,18 +289,10 @@ Item { model.position = getAbsolutePosition(Qt.point(newX, newY)); } onActiveChanged: { + model.interactiveMove = active; if (!active) { screen.resetTotalSize(); } } } - - // So we can show a grabby hand cursor when hovered over - MouseArea { - anchors.fill: parent - cursorShape: Qt.SizeAllCursor - acceptedButtons: Qt.NoButton // Otherwise it interferes with the drag handler - visible: kcm.outputModel && kcm.outputModel.rowCount() > 1 - } } - diff --git a/kcm/package/contents/ui/Screen.qml b/kcm/package/contents/ui/Screen.qml index 995f7a0..d7977cc 100644 --- a/kcm/package/contents/ui/Screen.qml +++ b/kcm/package/contents/ui/Screen.qml @@ -14,12 +14,12 @@ 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.9 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.3 as Controls -import org.kde.kirigami 2.5 as Kirigami +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 +import org.kde.kirigami 2.20 as Kirigami -Controls.ScrollView { +QQC2.ScrollView { property var outputs property size totalSize @@ -30,7 +30,7 @@ Controls.ScrollView { onWidthChanged: resetTotalSize() onHeightChanged: resetTotalSize() - property real relativeFactor: { + readonly property real relativeFactor: { var relativeSize = Qt.size(totalSize.width / (0.6 * width), totalSize.height / (0.6 * height)); if (relativeSize.width > relativeSize.height) { @@ -42,12 +42,8 @@ Controls.ScrollView { } } - property int xOffset: (width - totalSize.width / relativeFactor) / 2; - property int yOffset: (height - totalSize.height / relativeFactor) / 2; - - implicitHeight: Math.max(root.height * 0.4, Kirigami.Units.gridUnit * 13) - - Component.onCompleted: background.visible = true; + readonly property int xOffset: (width - totalSize.width / relativeFactor) / 2; + readonly property int yOffset: (height - totalSize.height / relativeFactor) / 2; Kirigami.Heading { z: 90 @@ -60,11 +56,11 @@ Controls.ScrollView { level: 4 opacity: 0.6 horizontalAlignment: Text.AlignHCenter - text: i18n("Drag displays to re-arrange them") + text: i18n("Drag screens to re-arrange them") visible: kcm.outputModel && kcm.outputModel.rowCount() > 1 } - Controls.Button { + QQC2.Button { anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter @@ -73,7 +69,7 @@ Controls.ScrollView { z: 90 onClicked: kcm.identifyOutputs() - text: i18nc("Itendifies displays with visual indicators", "Identify") + text: i18n("Identify") icon.name: "documentinfo" focusPolicy: Qt.NoFocus visible: kcm.outputModel && kcm.outputModel.rowCount() > 1 diff --git a/kcm/package/contents/ui/main.qml b/kcm/package/contents/ui/main.qml index d58906e..aa501ca 100644 --- a/kcm/package/contents/ui/main.qml +++ b/kcm/package/contents/ui/main.qml @@ -14,22 +14,74 @@ 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.15 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.3 as Controls -import org.kde.kirigami 2.4 as Kirigami +import QtQuick 2.15 as QtQuick +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 +import org.kde.kirigami 2.20 as Kirigami +import org.kde.kitemmodels 1.0 -import org.kde.kcm 1.2 as KCM +import org.kde.kcm 1.6 as KCM +import org.kwinft.private.kcm.kdisplay 1.0 as KDisplay KCM.SimpleKCM { id: root - implicitWidth: Kirigami.Units.gridUnit * 40 - implicitHeight: Kirigami.Units.gridUnit * 50 - property int selectedOutput: 0 + readonly property int topMargins: Kirigami.Units.smallSpacing + readonly property bool anyMessagesShown: invalidConfigMsg.visible + || errBackendMsg.visible + || errSaveMsg.visible + || scaleMsg.visible + || connectMsg.visible + + implicitWidth: Kirigami.Units.gridUnit * 32 + implicitHeight: Kirigami.Units.gridUnit * 30 + + topPadding: anyMessagesShown ? topMargins : 0 + leftPadding: 0 + rightPadding: 0 + + // This is to fix Output dragging + flickable.interactive: Kirigami.Settings.hasTransientTouchInput + + QtQuick.Connections { + target: kcm + function onInvalidConfig(reason) { + if (reason === KDisplay.KCMKDisplay.NoEnabledOutputs) { + invalidConfigMsg.text = i18nc("@info", "All displays are disabled. Enable at least one.") + } else if (reason === KDisplay.KCMKDisplay.ConfigHasGaps) { + invalidConfigMsg.text = i18nc("@info", "Gaps between displays are not supported. Make sure all displays are touching.") + } + invalidConfigMsg.visible = true; + } + function onErrorOnSave() { + errSaveMsg.visible = true; + } + function onGlobalScaleWritten() { + scaleMsg.visible = true; + } + function onOutputConnect(connected) { + if (connected) { + connectMsg.text = i18n("A new output has been added. Settings have been reloaded."); + } else { + connectMsg.text = i18n("An output has been removed. Settings have been reloaded."); + } + connectMsg.visible = true; + } + function onBackendError() { + errBackendMsg.visible = true; + } + function onChanged() { + invalidConfigMsg.visible = false; + errSaveMsg.visible = false; + scaleMsg.visible = false; + } + } + ColumnLayout { + spacing: Kirigami.Units.smallSpacing + Kirigami.InlineMessage { // Note1: There is an implicit height binding loop error on // first invocation. Seems to be an issue in Kirigami. @@ -37,27 +89,20 @@ KCM.SimpleKCM { // but there seems to be another issue in Kirigami then // being always hidden. Compare Night Color KCM with // the same issue. - id: dangerousSaveMsg + id: invalidConfigMsg Layout.fillWidth: true - type: Kirigami.MessageType.Warning - text: i18n("Are you sure you want to disable all displays? This might render the device unusable.") + Layout.leftMargin: root.topMargins + Layout.rightMargin: root.topMargins + type: Kirigami.MessageType.Error showCloseButton: true - actions: [ - Kirigami.Action { - iconName: "dialog-ok" - text: i18n("Disable all displays") - onTriggered: { - dangerousSaveMsg.visible = false; - kcm.forceSave(); - } - } - ] } Kirigami.InlineMessage { id: errBackendMsg Layout.fillWidth: true + Layout.leftMargin: root.topMargins + Layout.rightMargin: root.topMargins type: Kirigami.MessageType.Error text: i18n("No Disman backend found. Please check your Disman installation.") visible: false @@ -66,6 +111,8 @@ KCM.SimpleKCM { Kirigami.InlineMessage { id: errSaveMsg Layout.fillWidth: true + Layout.leftMargin: root.topMargins + Layout.rightMargin: root.topMargins type: Kirigami.MessageType.Error text: i18n("Displays could not be saved due to error.") visible: false @@ -74,23 +121,39 @@ KCM.SimpleKCM { Kirigami.InlineMessage { id: scaleMsg Layout.fillWidth: true - type: Kirigami.MessageType.Positive - text: i18n("New global scale applied. Change will come into effect after restart.") + Layout.leftMargin: root.topMargins + Layout.rightMargin: root.topMargins + type: Kirigami.MessageType.Information + text: i18n("Global scale changes will come into effect after the system is restarted.") visible: false showCloseButton: true + actions: [ + Kirigami.Action { + icon.name: "system-reboot" + text: i18n("Restart") + onTriggered: kcm.requestReboot(); + } + ] } Kirigami.InlineMessage { id: connectMsg Layout.fillWidth: true + Layout.leftMargin: root.topMargins + Layout.rightMargin: root.topMargins type: Kirigami.MessageType.Information visible: false showCloseButton: true } - Connections { + QtQuick.Connections { target: kcm - function onDangerousSave() { - dangerousSaveMsg.visible = true; + function onInvalidConfig(reason) { + if (reason === KDisplay.KCMKDisplay.NoEnabledOutputs) { + invalidConfigMsg.text = i18nc("@info", "All displays are disabled. Enable at least one.") + } else if (reason === KDisplay.KCMKDisplay.ConfigHasGaps) { + invalidConfigMsg.text = i18nc("@info", "Gaps between displays are not supported. Make sure all displays are touching.") + } + invalidConfigMsg.visible = true; } function onErrorOnSave() { errSaveMsg.visible = true; @@ -99,34 +162,55 @@ KCM.SimpleKCM { scaleMsg.visible = true; } function onOutputConnect(connected) { + root.selectedOutput = 0; if (connected) { - connectMsg.text = i18n("A new display has been added. Settings have been reloaded."); + connectMsg.text = i18n("A new output has been added. Settings have been reloaded."); } else { - connectMsg.text = i18n("A display has been removed. Settings have been reloaded."); + connectMsg.text = i18n("An output has been removed. Settings have been reloaded."); } connectMsg.visible = true; } function onBackendError() { errBackendMsg.visible = true; } - function onChanged() { - dangerousSaveMsg.visible = false; + invalidConfigMsg.visible = false; errSaveMsg.visible = false; scaleMsg.visible = false; } } - Screen { - id: screen + QtQuick.Rectangle { + Layout.preferredHeight: Math.max(root.height * 0.4, Kirigami.Units.gridUnit * 13) + Layout.fillWidth: true + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.View + color: Kirigami.Theme.backgroundColor + + Kirigami.Separator { + anchors { + top: parent.top + left: parent.left + right: parent.right + } + visible: root.anyMessagesShown + } - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: Math.max(root.width * 0.8, Kirigami.Units.gridUnit * 26) - Layout.topMargin: Kirigami.Units.smallSpacing - Layout.bottomMargin: Kirigami.Units.largeSpacing + Screen { + id: screen - enabled: kcm.outputModel && kcm.backendReady - outputs: kcm.outputModel + anchors.fill: parent + enabled: kcm.outputModel && kcm.backendReady + outputs: kcm.outputModel + } + + Kirigami.Separator { + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } } Panel { diff --git a/kcm/po/kcm_kdisplay.pot b/kcm/po/kcm_kdisplay.pot index cbc7349..8d81a3b 100644 --- a/kcm/po/kcm_kdisplay.pot +++ b/kcm/po/kcm_kdisplay.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-03-31 00:13+0200\n" +"POT-Creation-Date: 2023-04-16 21:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -66,19 +66,22 @@ msgstr "" msgid "Orientation:" msgstr "" -#: kcm/package/contents/ui/Orientation.qml:36 -#: kcm/package/contents/ui/OutputPanel.qml:114 -#: kcm/package/contents/ui/OutputPanel.qml:141 +#: kcm/package/contents/ui/Orientation.qml:37 #, kde-format -msgid "Auto" +msgid "Automatic" +msgstr "" + +#: kcm/package/contents/ui/Orientation.qml:46 +#, kde-format +msgid "Only when in tablet mode" msgstr "" -#: kcm/package/contents/ui/Orientation.qml:42 +#: kcm/package/contents/ui/Orientation.qml:55 #, kde-format -msgid "Only when in tablet mode." +msgid "Manual" msgstr "" -#: kcm/package/contents/ui/Output.qml:154 +#: kcm/package/contents/ui/Output.qml:247 #, kde-format msgid "Replicas" msgstr "" @@ -110,6 +113,12 @@ msgstr "" msgid "Resolution:" msgstr "" +#: kcm/package/contents/ui/OutputPanel.qml:114 +#: kcm/package/contents/ui/OutputPanel.qml:141 +#, kde-format +msgid "Auto" +msgstr "" + #: kcm/package/contents/ui/OutputPanel.qml:133 #: kcm/package/contents/ui/OutputPanel.qml:148 #, kde-format @@ -178,50 +187,56 @@ msgstr "" msgid "No Rotation" msgstr "" -#: kcm/package/contents/ui/Screen.qml:63 +#: kcm/package/contents/ui/Screen.qml:59 #, kde-format -msgid "Drag displays to re-arrange them" +msgid "Drag screens to re-arrange them" msgstr "" -#: kcm/package/contents/ui/Screen.qml:76 +#: kcm/package/contents/ui/Screen.qml:72 #, kde-format -msgctxt "Itendifies displays with visual indicators" msgid "Identify" msgstr "" -#: kcm/package/contents/ui/main.qml:44 +#: kcm/package/contents/ui/main.qml:51 kcm/package/contents/ui/main.qml:152 +#, kde-format +msgctxt "@info" +msgid "All displays are disabled. Enable at least one." +msgstr "" + +#: kcm/package/contents/ui/main.qml:53 kcm/package/contents/ui/main.qml:154 #, kde-format +msgctxt "@info" msgid "" -"Are you sure you want to disable all displays? This might render the device " -"unusable." +"Gaps between displays are not supported. Make sure all displays are touching." msgstr "" -#: kcm/package/contents/ui/main.qml:50 +#: kcm/package/contents/ui/main.qml:65 kcm/package/contents/ui/main.qml:167 #, kde-format -msgid "Disable all displays" +msgid "A new output has been added. Settings have been reloaded." msgstr "" -#: kcm/package/contents/ui/main.qml:62 +#: kcm/package/contents/ui/main.qml:67 kcm/package/contents/ui/main.qml:169 #, kde-format -msgid "No Disman backend found. Please check your Disman installation." +msgid "An output has been removed. Settings have been reloaded." msgstr "" -#: kcm/package/contents/ui/main.qml:70 +#: kcm/package/contents/ui/main.qml:107 #, kde-format -msgid "Displays could not be saved due to error." +msgid "No Disman backend found. Please check your Disman installation." msgstr "" -#: kcm/package/contents/ui/main.qml:78 +#: kcm/package/contents/ui/main.qml:117 #, kde-format -msgid "New global scale applied. Change will come into effect after restart." +msgid "Displays could not be saved due to error." msgstr "" -#: kcm/package/contents/ui/main.qml:103 +#: kcm/package/contents/ui/main.qml:127 #, kde-format -msgid "A new display has been added. Settings have been reloaded." +msgid "" +"Global scale changes will come into effect after the system is restarted." msgstr "" -#: kcm/package/contents/ui/main.qml:105 +#: kcm/package/contents/ui/main.qml:133 #, kde-format -msgid "A display has been removed. Settings have been reloaded." +msgid "Restart" msgstr ""