From 30a72eeaff89fab3dbcc2ed7142783e7d35c8060 Mon Sep 17 00:00:00 2001 From: Zixing Liu Date: Mon, 13 Jul 2020 15:54:12 -0600 Subject: [PATCH 1/2] feat(kcm): add revert timer add a revert timer that will revert the settings if user does not response in 30 seconds Signed-off-by: Zixing Liu --- kcm/config_handler.cpp | 1 + kcm/config_handler.h | 5 +++ kcm/kcm.cpp | 23 +++++++++++ kcm/kcm.h | 4 ++ kcm/package/contents/ui/main.qml | 67 +++++++++++++++++++++++++++++++- 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/kcm/config_handler.cpp b/kcm/config_handler.cpp index ce1ce0f1..99234704 100644 --- a/kcm/config_handler.cpp +++ b/kcm/config_handler.cpp @@ -97,6 +97,7 @@ void ConfigHandler::initOutput(const KScreen::OutputPtr &output) void ConfigHandler::updateInitialData() { + m_previousConfig = m_initialConfig->clone(); m_initialRetention = getRetention(); connect(new GetConfigOperation(), &GetConfigOperation::finished, this, [this](ConfigOperation *op) { if (op->hasError()) { diff --git a/kcm/config_handler.h b/kcm/config_handler.h index ad3fb11b..aa49d147 100644 --- a/kcm/config_handler.h +++ b/kcm/config_handler.h @@ -51,6 +51,10 @@ public: return m_initialConfig; } + void revertConfig() { + m_config = m_previousConfig->clone(); + } + int retention() const; void setRetention(int retention); @@ -94,6 +98,7 @@ private: KScreen::ConfigPtr m_config = nullptr; KScreen::ConfigPtr m_initialConfig; + KScreen::ConfigPtr m_previousConfig = nullptr; OutputModel *m_outputs = nullptr; std::unique_ptr m_control; diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index 90bc0dd0..bf107b00 100644 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -100,6 +100,21 @@ void KCMKScreen::save() doSave(false); } +void KCMKScreen::revertSettings() +{ + if (!m_config) { + setNeedsSave(false); + return; + } + if (!m_settingsReverted) { + m_config->revertConfig(); + m_settingsReverted = true; + doSave(true); + load(); // reload the configuration + Q_EMIT settingsReverted(); + } +} + void KCMKScreen::doSave(bool force) { if (!m_config) { @@ -159,6 +174,14 @@ void KCMKScreen::doSave(bool force) } m_config->updateInitialData(); }); + // Show the revert warning dialog + if (!m_settingsReverted) { + // start the revert timer + Q_EMIT showRevertWarning(); + } else { + // reset the revert flag + m_settingsReverted = false; + } } bool KCMKScreen::backendReady() const diff --git a/kcm/kcm.h b/kcm/kcm.h index b33eaa7c..e29a30dd 100644 --- a/kcm/kcm.h +++ b/kcm/kcm.h @@ -77,6 +77,7 @@ public: Q_INVOKABLE void forceSave(); void doSave(bool force); + Q_INVOKABLE void revertSettings(); Q_SIGNALS: void backendReadyChanged(); @@ -96,6 +97,8 @@ Q_SIGNALS: void errorOnSave(); void globalScaleWritten(); void outputConnect(bool connected); + void settingsReverted(); + void showRevertWarning(); private: void setBackendReady(bool error); @@ -112,6 +115,7 @@ private: OrientationSensor *m_orientationSensor; bool m_backendReady = false; bool m_screenNormalized = true; + bool m_settingsReverted = false; double m_globalScale = 1.; double m_initialGlobalScale = 1.; diff --git a/kcm/package/contents/ui/main.qml b/kcm/package/contents/ui/main.qml index 8cb3375d..6c227bf2 100644 --- a/kcm/package/contents/ui/main.qml +++ b/kcm/package/contents/ui/main.qml @@ -16,7 +16,8 @@ along with this program. If not, see . *********************************************************************/ import QtQuick 2.15 import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.3 as Controls +import QtQuick.Controls 2.15 as Controls +import QtQuick.Dialogs 1.3 import org.kde.kirigami 2.4 as Kirigami import org.kde.kcm 1.2 as KCM @@ -28,6 +29,10 @@ KCM.SimpleKCM { implicitHeight: Kirigami.Units.gridUnit * 38 property int selectedOutput: 0 + property int revertCountdown: 30 + + readonly property var configConfirmMsg: "Are you happy with this configuration?
Settings will be reverted in 1 second." + readonly property var configConfirmMsgN: "Are you happy with this configuration?
Settings will be reverted in %1 seconds." ColumnLayout { Kirigami.InlineMessage { @@ -86,6 +91,35 @@ KCM.SimpleKCM { visible: false showCloseButton: true } + Kirigami.InlineMessage { + id: revertMsg + Layout.fillWidth: true + type: Kirigami.MessageType.Information + text: i18n("Display settings reverted.") + visible: false + showCloseButton: true + } + Dialog { + id: confirmMsg + visible: false + standardButtons: Dialog.Apply | Dialog.Discard + + Controls.Label { + id: confirmMsgLabel + } + + onDiscard: { + confirmMsg.close(); + // stop the timer + revertTimer.stop(); + // reset the settings + kcm.revertSettings(); + } + onApply: { + confirmMsg.visible = false; + revertTimer.stop(); + } + } Connections { target: kcm @@ -110,6 +144,18 @@ KCM.SimpleKCM { errBackendMsg.visible = true; } + onBackendError: errBackendMsg.visible = true; + onSettingsReverted: { + revertMsg.visible = true; + confirmMsg.visible = false; + } + onShowRevertWarning: { + revertCountdown = 30; + confirmMsgLabel.text = i18np(configConfirmMsg, configConfirmMsgN, revertCountdown); + confirmMsg.visible = true; + revertTimer.restart(); + } + function onChanged() { dangerousSaveMsg.visible = false; errSaveMsg.visible = false; @@ -133,5 +179,24 @@ KCM.SimpleKCM { enabled: kcm.outputModel && kcm.backendReady Layout.fillWidth: true } + + Timer { + id: revertTimer + interval: 1000 + running: false + repeat: true + + onTriggered: { + revertCountdown -= 1; + if (revertCountdown < 1) { + // stop the timer + this.stop(); + // reset the settings + kcm.revertSettings(); + return; + } + confirmMsgLabel.text = i18np(configConfirmMsg, configConfirmMsgN, revertCountdown); + } + } } } -- GitLab From ded3aa249aa3b56a9d0fff9435c3ebf4487c003c Mon Sep 17 00:00:00 2001 From: Chris Rizzitello Date: Wed, 18 Aug 2021 22:12:20 -0400 Subject: [PATCH 2/2] Do not show revert when not changing screen --- kcm/config_handler.cpp | 56 +++++++++++-------- kcm/config_handler.h | 11 +++- kcm/kcm.cpp | 14 ++--- kcm/package/contents/ui/main.qml | 96 +++++++++++++++++++++----------- 4 files changed, 111 insertions(+), 66 deletions(-) diff --git a/kcm/config_handler.cpp b/kcm/config_handler.cpp index 99234704..3aea6b15 100644 --- a/kcm/config_handler.cpp +++ b/kcm/config_handler.cpp @@ -23,6 +23,7 @@ along with this program. If not, see . #include #include +#include #include using namespace KScreen; @@ -112,6 +113,11 @@ void ConfigHandler::updateInitialData() }); } +bool ConfigHandler::shouldTestNewSettings() +{ + return checkSaveandTestCommon(false); +} + void ConfigHandler::checkNeedsSave() { if (m_config->supportedFeatures() & KScreen::Config::Feature::PrimaryDisplay) { @@ -130,40 +136,44 @@ void ConfigHandler::checkNeedsSave() Q_EMIT needsSaveChecked(true); return; } + Q_EMIT needsSaveChecked(checkSaveandTestCommon(true)); +} - for (const auto &output : m_config->connectedOutputs()) { +bool ConfigHandler::checkSaveandTestCommon(bool isSaveCheck) +{ + const auto outputs = m_config->connectedOutputs(); + for (const auto &output : outputs) { const QString hash = output->hashMd5(); - for (const auto &initialOutput : m_initialConfig->outputs()) { - if (hash != initialOutput->hashMd5()) { + const auto configs = m_initialConfig->outputs(); + for (const auto &config : configs) { + if (hash != config->hashMd5()) { continue; } - bool needsSave = false; - if (output->isEnabled() != initialOutput->isEnabled()) { - needsSave = true; + + if (output->isEnabled() != config->isEnabled()) { + return true; } + // clang-format off if (output->isEnabled()) { - needsSave |= output->currentModeId() != - initialOutput->currentModeId() - || output->pos() != initialOutput->pos() - || output->scale() != initialOutput->scale() - || output->rotation() != initialOutput->rotation() - || output->replicationSource() != initialOutput->replicationSource() - || autoRotate(output) != m_initialControl->getAutoRotate(output) - || autoRotateOnlyInTabletMode(output) - != m_initialControl->getAutoRotateOnlyInTabletMode(output) - || output->overscan() != initialOutput->overscan() - || output->vrrPolicy() != initialOutput->vrrPolicy(); + bool realScaleChange = output->scale() != config->scale(); + bool scaleChanged = isSaveCheck ? realScaleChange : qGuiApp->platformName() == QLatin1String("wayland") ? realScaleChange : false; + if ( output->currentModeId() != config->currentModeId() + || output->pos() != config->pos() + || scaleChanged + || output->rotation() != config->rotation() + || output->replicationSource() != config->replicationSource() + || autoRotate(output) != m_initialControl->getAutoRotate(output) + || autoRotateOnlyInTabletMode(output) != m_initialControl->getAutoRotateOnlyInTabletMode(output) + || output->overscan() != config->overscan() + || output->vrrPolicy() != config->vrrPolicy()) { + return true; + } } // clang-format on - if (needsSave) { - Q_EMIT needsSaveChecked(true); - return; - } - break; } } - Q_EMIT needsSaveChecked(false); + return false; } QSize ConfigHandler::screenSize() const diff --git a/kcm/config_handler.h b/kcm/config_handler.h index aa49d147..c8dfd869 100644 --- a/kcm/config_handler.h +++ b/kcm/config_handler.h @@ -51,7 +51,8 @@ public: return m_initialConfig; } - void revertConfig() { + void revertConfig() + { m_config = m_previousConfig->clone(); } @@ -78,6 +79,7 @@ public: void writeControl(); void checkNeedsSave(); + bool shouldTestNewSettings(); Q_SIGNALS: void outputModelChanged(); @@ -95,6 +97,13 @@ private: void primaryOutputChanged(const KScreen::OutputPtr &output); void initOutput(const KScreen::OutputPtr &output); void resetScale(const KScreen::OutputPtr &output); + /** + * @brief checkSaveandTestCommon - compairs common config changes that would make the config dirty and needed to have the config checked when applied. + * @param isSaveCheck - True if your checking to see if the changes should request a save. + * False if you want to check if you should test the config when applied. + * @return true, if you should check for a save or test the new configuration + */ + bool checkSaveandTestCommon(bool isSaveCheck); KScreen::ConfigPtr m_config = nullptr; KScreen::ConfigPtr m_initialConfig; diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index bf107b00..bd5ff04a 100644 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -173,15 +173,13 @@ void KCMKScreen::doSave(bool force) return; } m_config->updateInitialData(); + + if (!m_settingsReverted && m_config->shouldTestNewSettings()) { + Q_EMIT showRevertWarning(); + } else { + m_settingsReverted = false; + } }); - // Show the revert warning dialog - if (!m_settingsReverted) { - // start the revert timer - Q_EMIT showRevertWarning(); - } else { - // reset the revert flag - m_settingsReverted = false; - } } bool KCMKScreen::backendReady() const diff --git a/kcm/package/contents/ui/main.qml b/kcm/package/contents/ui/main.qml index 6c227bf2..15bb16f0 100644 --- a/kcm/package/contents/ui/main.qml +++ b/kcm/package/contents/ui/main.qml @@ -17,9 +17,8 @@ along with this program. If not, see . import QtQuick 2.15 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.15 as Controls -import QtQuick.Dialogs 1.3 -import org.kde.kirigami 2.4 as Kirigami +import org.kde.kirigami 2.7 as Kirigami import org.kde.kcm 1.2 as KCM KCM.SimpleKCM { @@ -31,9 +30,6 @@ KCM.SimpleKCM { property int selectedOutput: 0 property int revertCountdown: 30 - readonly property var configConfirmMsg: "Are you happy with this configuration?
Settings will be reverted in 1 second." - readonly property var configConfirmMsgN: "Are you happy with this configuration?
Settings will be reverted in %1 seconds." - ColumnLayout { Kirigami.InlineMessage { // Note1: There is an implicit height binding loop error on @@ -95,29 +91,68 @@ KCM.SimpleKCM { id: revertMsg Layout.fillWidth: true type: Kirigami.MessageType.Information - text: i18n("Display settings reverted.") + text: i18n("Display configuration reverted.") visible: false showCloseButton: true } - Dialog { + Kirigami.OverlaySheet { id: confirmMsg - visible: false - standardButtons: Dialog.Apply | Dialog.Discard - - Controls.Label { - id: confirmMsgLabel + property bool keepConfig: false + property bool userInteraction: false + parent: root.parent + title: i18n("Keep display configuration?") + onSheetOpenChanged: { + if (sheetOpen) { + revertButton.forceActiveFocus() + confirmMsg.keepConfig = false + confirmMsg.userInteraction = false + } else { + if (!confirmMsg.keepConfig) { + kcm.revertSettings() + if (!confirmMsg.userInteraction) { + revertMsg.visible = true + } + } + revertTimer.stop() + } } - - onDiscard: { - confirmMsg.close(); - // stop the timer - revertTimer.stop(); - // reset the settings - kcm.revertSettings(); + showCloseButton: false + contentItem: Controls.Label { + text: i18np("Will revert to previous configuration in %1 second.", + "Will revert to previous configuration in %1 seconds.", + revertCountdown); + wrapMode: Qt.WordWrap } - onApply: { - confirmMsg.visible = false; - revertTimer.stop(); + footer: RowLayout { + Controls.Button { + id: acceptButton + Layout.fillWidth: true + action: Controls.Action { + icon.name: "dialog-ok" + text: i18n("&Keep") + shortcut: "Return" + onTriggered: { + confirmMsg.keepConfig = true + confirmMsg.userInteraction = true + confirmMsg.close() + } + } + } + Controls.Button { + id: revertButton + Layout.fillWidth: true + KeyNavigation.left: acceptButton + focus: true + action: Controls.Action { + icon.name: "edit-undo" + text: i18n("&Revert") + shortcut: "Escape" + onTriggered: { + confirmMsg.userInteraction = true + confirmMsg.close() + } + } + } } } @@ -143,23 +178,19 @@ KCM.SimpleKCM { function onBackendError() { errBackendMsg.visible = true; } - - onBackendError: errBackendMsg.visible = true; - onSettingsReverted: { - revertMsg.visible = true; - confirmMsg.visible = false; + function onSettingsReverted() { + confirmMsg.close(); } - onShowRevertWarning: { + function onShowRevertWarning() { revertCountdown = 30; - confirmMsgLabel.text = i18np(configConfirmMsg, configConfirmMsgN, revertCountdown); - confirmMsg.visible = true; + confirmMsg.open(); revertTimer.restart(); } - function onChanged() { dangerousSaveMsg.visible = false; errSaveMsg.visible = false; scaleMsg.visible = false; + revertMsg.visible = false; } } @@ -189,13 +220,10 @@ KCM.SimpleKCM { onTriggered: { revertCountdown -= 1; if (revertCountdown < 1) { - // stop the timer this.stop(); - // reset the settings kcm.revertSettings(); return; } - confirmMsgLabel.text = i18np(configConfirmMsg, configConfirmMsgN, revertCountdown); } } } -- GitLab