diff --git a/README.md b/README.md index cf5d49f..f52184c 100644 --- a/README.md +++ b/README.md @@ -197,8 +197,8 @@ On macOS, disable it by editing the property list for the application: defaults write org.raspberrypi.Imager.plist telemetry -bool NO ``` -### Advanced options +### OS Customization -When using the app, press CTRL + SHIFT + X to reveal the **Advanced options** dialog. +When using the app, press CTRL + SHIFT + X to reveal the **OS Customization** dialog. In here, you can specify several things you would otherwise set in the boot configuration files. For example, you can enable SSH, set the Wi-Fi login, and specify your locale settings for the system image. diff --git a/embedded/imager/package/rpi-imager/0001-rpi-imager-change-window-to-popup.patch b/embedded/imager/package/rpi-imager/0001-rpi-imager-change-window-to-popup.patch index 6ebfa1a..70d45ab 100644 --- a/embedded/imager/package/rpi-imager/0001-rpi-imager-change-window-to-popup.patch +++ b/embedded/imager/package/rpi-imager/0001-rpi-imager-change-window-to-popup.patch @@ -24,6 +24,6 @@ index 568d1cd..9e36607 100644 + function raise() { } + /* */ + - title: qsTr("Advanced options") + title: qsTr("OS Customization") property bool initialized: false diff --git a/src/OptionsPopup.qml b/src/OptionsPopup.qml index 568d1cd..c333098 100644 --- a/src/OptionsPopup.qml +++ b/src/OptionsPopup.qml @@ -17,7 +17,7 @@ Window { maximumWidth: width minimumHeight: 125 height: Math.min(750, cl.implicitHeight) - title: qsTr("Advanced options") + title: qsTr("OS Customization") property bool initialized: false property bool hasSavedSettings: false @@ -29,6 +29,8 @@ Window { property string cloudinitwrite property string cloudinitnetwork + signal saveSettingsSignal(var settings) + ColumnLayout { id: cl spacing: 10 @@ -46,23 +48,6 @@ Window { //ScrollBar.vertical.policy: ScrollBar.AlwaysOn ColumnLayout { - - RowLayout { - Label { - text: qsTr("Image customization options") - } - ComboBox { - id: comboSaveSettings - model: { - [qsTr("for this session only"), - qsTr("to always use")] - } - Layout.minimumWidth: 250 - Layout.maximumHeight: 40 - enabled: !imageWriter.isEmbeddedMode() - } - } - TabBar { id: bar Layout.fillWidth: true @@ -453,7 +438,6 @@ Window { fieldKeyboardLayout.model = imageWriter.getKeymapLayoutList() if (Object.keys(settings).length) { - comboSaveSettings.currentIndex = 1 hasSavedSettings = true } if ('hostname' in settings) { @@ -539,7 +523,7 @@ Window { /* Lacking an easy cross-platform to fetch keyboard layout from host system, just default to "gb" for people in UK time zone for now, and "us" for everyone else */ - if (tz == "Europe/London") { + if (tz === "Europe/London") { fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("gb") } else { fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("us") @@ -807,43 +791,85 @@ Window { function saveSettings() { - if (comboSaveSettings.currentIndex == 1) { - hasSavedSettings = true - var settings = { }; - if (chkHostname.checked && fieldHostname.length) { - settings.hostname = fieldHostname.text - } - if (chkSetUser.checked) { - settings.sshUserName = fieldUserName.text - settings.sshUserPassword = fieldUserPassword.alreadyCrypted ? fieldUserPassword.text : imageWriter.crypt(fieldUserPassword.text) - } + var settings = { }; + if (chkHostname.checked && fieldHostname.length) { + settings.hostname = fieldHostname.text + } + if (chkSetUser.checked) { + settings.sshUserName = fieldUserName.text + settings.sshUserPassword = fieldUserPassword.alreadyCrypted ? fieldUserPassword.text : imageWriter.crypt(fieldUserPassword.text) + } - settings.sshEnabled = chkSSH.checked - if (chkSSH.checked && radioPubKeyAuthentication.checked) { - settings.sshAuthorizedKeys = fieldPublicKey.text + settings.sshEnabled = chkSSH.checked + if (chkSSH.checked && radioPubKeyAuthentication.checked) { + settings.sshAuthorizedKeys = fieldPublicKey.text + } + if (chkWifi.checked) { + settings.wifiSSID = fieldWifiSSID.text + if (chkWifiSSIDHidden.checked) { + settings.wifiSSIDHidden = true } - if (chkWifi.checked) { - settings.wifiSSID = fieldWifiSSID.text - if (chkWifiSSIDHidden.checked) { - settings.wifiSSIDHidden = true - } - settings.wifiPassword = fieldWifiPassword.text.length == 64 ? fieldWifiPassword.text : imageWriter.pbkdf2(fieldWifiPassword.text, fieldWifiSSID.text) - settings.wifiCountry = fieldWifiCountry.editText - } - if (chkLocale.checked) { - settings.timezone = fieldTimezone.editText - settings.keyboardLayout = fieldKeyboardLayout.editText - } - - imageWriter.setSavedCustomizationSettings(settings) - - } else if (hasSavedSettings) { - imageWriter.clearSavedCustomizationSettings() - hasSavedSettings = false + settings.wifiPassword = fieldWifiPassword.text.length == 64 ? fieldWifiPassword.text : imageWriter.pbkdf2(fieldWifiPassword.text, fieldWifiSSID.text) + settings.wifiCountry = fieldWifiCountry.editText + } + if (chkLocale.checked) { + settings.timezone = fieldTimezone.editText + settings.keyboardLayout = fieldKeyboardLayout.editText } imageWriter.setSetting("beep", chkBeep.checked) imageWriter.setSetting("eject", chkEject.checked) imageWriter.setSetting("telemetry", chkTelemtry.checked) + + if (chkHostname.checked || chkSetUser.checked || chkSSH.checked || chkWifi.checked || chkLocale.checked) { + /* OS customization to be applied. */ + hasSavedSettings = true + saveSettingsSignal(settings) + } + } + + function clearCustomizationFields() + { + /* Bind copies of the lists */ + fieldTimezone.model = imageWriter.getTimezoneList() + fieldKeyboardLayout.model = imageWriter.getKeymapLayoutList() + fieldWifiCountry.model = imageWriter.getCountryList() + + fieldHostname.text = "raspberrypi" + fieldUserName.text = imageWriter.getCurrentUser() + fieldUserPassword.clear() + radioPubKeyAuthentication.checked = false + radioPasswordAuthentication.checked = false + fieldPublicKey.clear() + + /* Timezone Settings*/ + fieldTimezone.currentIndex = fieldTimezone.find(imageWriter.getTimezone()) + /* Lacking an easy cross-platform to fetch keyboard layout + from host system, just default to "gb" for people in + UK time zone for now, and "us" for everyone else */ + if (imageWriter.getTimezone() === "Europe/London") { + fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("gb") + } else { + fieldKeyboardLayout.currentIndex = fieldKeyboardLayout.find("us") + } + + chkSetUser.checked = false + chkSSH.checked = false + chkLocale.checked = false + chkWifiSSIDHidden.checked = false + chkHostname.checked = false + + /* WiFi Settings */ + fieldWifiSSID.text = imageWriter.getSSID() + if (fieldWifiSSID.text.length) { + fieldWifiPassword.text = imageWriter.getPSK() + if (fieldWifiPassword.text.length) { + chkShowPassword.checked = false + if (Qt.platform.os == "osx") { + /* User indicated wifi must be prefilled */ + chkWifi.checked = true + } + } + } } } diff --git a/src/UseSavedSettingsPopup.qml b/src/UseSavedSettingsPopup.qml index f002763..a6b60d7 100644 --- a/src/UseSavedSettingsPopup.qml +++ b/src/UseSavedSettingsPopup.qml @@ -18,6 +18,8 @@ Popup { padding: 0 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + property bool hasSavedSettings: false + signal yes() signal no() signal noClearSettings() @@ -70,7 +72,7 @@ Popup { Layout.topMargin: 10 font.family: roboto.name font.bold: true - text: qsTr("Use image customisation?") + text: qsTr("Use OS customization?") } Text { @@ -85,7 +87,7 @@ Popup { Layout.topMargin: 25 Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Accessible.name: text.replace(/<\/?[^>]+(>|$)/g, "") - text: qsTr("Would you like to apply image customization settings?") + text: qsTr("Would you like to apply OS customization settings?") } RowLayout { @@ -94,38 +96,6 @@ Popup { spacing: 20 id: buttons - ImButton { - text: qsTr("NO") - onClicked: { - msgpopup.close() - msgpopup.no() - } - Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" - Material.background: "#c51a4a" - } - - ImButton { - text: qsTr("NO, CLEAR SETTINGS") - onClicked: { - msgpopup.close() - msgpopup.noClearSettings() - } - Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" - Material.background: "#c51a4a" - enabled: imageWriter.hasSavedCustomizationSettings() ? true : false - } - - ImButton { - text: qsTr("YES") - onClicked: { - msgpopup.close() - msgpopup.yes() - } - Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" - Material.background: "#c51a4a" - enabled: imageWriter.hasSavedCustomizationSettings() ? true : false - } - ImButton { text: qsTr("EDIT SETTINGS") onClicked: { @@ -136,12 +106,56 @@ Popup { Material.background: "#c51a4a" } + ImButton { + id: noAndClearButton + text: qsTr("NO, CLEAR SETTINGS") + onClicked: { + msgpopup.close() + msgpopup.noClearSettings() + } + Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" + Material.background: "#c51a4a" + enabled: false + } + + ImButton { + id: yesButton + text: qsTr("YES") + onClicked: { + msgpopup.close() + msgpopup.yes() + } + Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" + Material.background: "#c51a4a" + enabled: false + } + + ImButton { + text: qsTr("NO") + onClicked: { + msgpopup.close() + msgpopup.no() + } + Material.foreground: activeFocus ? "#d1dcfb" : "#ffffff" + Material.background: "#c51a4a" + } + Text { text: " " } } } function openPopup() { open() + if (hasSavedSettings) { + /* HACK: Bizarrely, the button enabled characteristics are not re-evaluated on open. + * So, let's manually _force_ these buttons to be enabled */ + yesButton.enabled = true + noAndClearButton.enabled = true + } else { + yesButton.enabled = false + noAndClearButton.enabled = false + } + // trigger screen reader to speak out message msgpopupbody.forceActiveFocus() } diff --git a/src/i18n/rpi-imager_ca.ts b/src/i18n/rpi-imager_ca.ts index 4239a25..123d79f 100644 --- a/src/i18n/rpi-imager_ca.ts +++ b/src/i18n/rpi-imager_ca.ts @@ -282,13 +282,13 @@ OptionsPopup - Advanced options - Opcions avançades + OS customization + - Image customization options - Opcions de personalització de les imatges + OS customization options + diff --git a/src/i18n/rpi-imager_de.ts b/src/i18n/rpi-imager_de.ts index e252d53..a5f15bd 100644 --- a/src/i18n/rpi-imager_de.ts +++ b/src/i18n/rpi-imager_de.ts @@ -319,13 +319,13 @@ OptionsPopup - Advanced options - Erweiterte Optionen + OS customization + - Image customization options - OS-Modifizierungen + OS customization options + diff --git a/src/i18n/rpi-imager_en.ts b/src/i18n/rpi-imager_en.ts index 0a302ee..16cb85c 100644 --- a/src/i18n/rpi-imager_en.ts +++ b/src/i18n/rpi-imager_en.ts @@ -278,12 +278,12 @@ OptionsPopup - Advanced options + OS customization - Image customization options + OS customization options diff --git a/src/i18n/rpi-imager_es.ts b/src/i18n/rpi-imager_es.ts index 8d35c96..d64b7c6 100644 --- a/src/i18n/rpi-imager_es.ts +++ b/src/i18n/rpi-imager_es.ts @@ -282,13 +282,13 @@ OptionsPopup - Advanced options - Opciones avanzadas + OS customization + - Image customization options - Opciones de personalización de imagen + OS customization options + diff --git a/src/i18n/rpi-imager_fr.ts b/src/i18n/rpi-imager_fr.ts index dabf454..e07417a 100644 --- a/src/i18n/rpi-imager_fr.ts +++ b/src/i18n/rpi-imager_fr.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - Réglages avancés + OS customization + - Image customization options - Options de personnalisation de l'image + OS customization options + diff --git a/src/i18n/rpi-imager_it.ts b/src/i18n/rpi-imager_it.ts index d328c52..67bb9e1 100644 --- a/src/i18n/rpi-imager_it.ts +++ b/src/i18n/rpi-imager_it.ts @@ -319,13 +319,13 @@ Aggiungi sia 'rpi-imager.exe' che 'fat32format.exe' all&apos OptionsPopup - Advanced options - Opzioni avanzate + OS customization + - Image customization options - Opzioni personalizzazione immagine + OS customization options + diff --git a/src/i18n/rpi-imager_ja.ts b/src/i18n/rpi-imager_ja.ts index 0268bda..f689f50 100644 --- a/src/i18n/rpi-imager_ja.ts +++ b/src/i18n/rpi-imager_ja.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - 詳細な設定 + OS customization + - Image customization options - イメージカスタマイズオプション + OS customization options + diff --git a/src/i18n/rpi-imager_ko.ts b/src/i18n/rpi-imager_ko.ts index e1a36f3..d2602e1 100644 --- a/src/i18n/rpi-imager_ko.ts +++ b/src/i18n/rpi-imager_ko.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - 고급 옵션 + OS customization + - Image customization options - 이미지 사용자 정의 옵션 + OS customization options + diff --git a/src/i18n/rpi-imager_nl.ts b/src/i18n/rpi-imager_nl.ts index 0786b63..d2ce1bc 100644 --- a/src/i18n/rpi-imager_nl.ts +++ b/src/i18n/rpi-imager_nl.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - Geavanceerde instellingen + OS customization + - Image customization options - Image instellingen + OS customization options + diff --git a/src/i18n/rpi-imager_ru.ts b/src/i18n/rpi-imager_ru.ts index 8b9062e..e97ac87 100644 --- a/src/i18n/rpi-imager_ru.ts +++ b/src/i18n/rpi-imager_ru.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - Дополнительные параметры + OS customization + - Image customization options - Параметры настройки образа + OS customization options + diff --git a/src/i18n/rpi-imager_sk.ts b/src/i18n/rpi-imager_sk.ts index be70d81..a3578ab 100644 --- a/src/i18n/rpi-imager_sk.ts +++ b/src/i18n/rpi-imager_sk.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - Pokročilé možnosti + OS customization + - Image customization options - Možnosti úprav obrazu + OS customization options + diff --git a/src/i18n/rpi-imager_sl.ts b/src/i18n/rpi-imager_sl.ts index 07965dc..4624545 100644 --- a/src/i18n/rpi-imager_sl.ts +++ b/src/i18n/rpi-imager_sl.ts @@ -318,13 +318,13 @@ OptionsPopup - Advanced options - Napredne možnosti + OS customization + - Image customization options - Uporabi opcije prilagoditve slike diska + OS customization options + diff --git a/src/i18n/rpi-imager_tr.ts b/src/i18n/rpi-imager_tr.ts index 42f9b86..53abf54 100644 --- a/src/i18n/rpi-imager_tr.ts +++ b/src/i18n/rpi-imager_tr.ts @@ -290,12 +290,12 @@ OptionsPopup - Advanced options + OS customization - Image customization options + OS customization options diff --git a/src/i18n/rpi-imager_uk.ts b/src/i18n/rpi-imager_uk.ts index cf8f099..3cdb6cf 100644 --- a/src/i18n/rpi-imager_uk.ts +++ b/src/i18n/rpi-imager_uk.ts @@ -282,13 +282,13 @@ OptionsPopup - Advanced options - Розширені налаштування + OS customization + - Image customization options - Налаштування образу + OS customization options + diff --git a/src/i18n/rpi-imager_zh.ts b/src/i18n/rpi-imager_zh.ts index 3ab8a83..cb83a6a 100644 --- a/src/i18n/rpi-imager_zh.ts +++ b/src/i18n/rpi-imager_zh.ts @@ -306,13 +306,13 @@ OptionsPopup - Advanced options - 高级设置 + OS customization + - Image customization options - 镜像自定义选项 + OS customization options + diff --git a/src/imagewriter.cpp b/src/imagewriter.cpp index 5d5b397..2a86281 100644 --- a/src/imagewriter.cpp +++ b/src/imagewriter.cpp @@ -1039,6 +1039,7 @@ void ImageWriter::setSavedCustomizationSettings(const QVariantMap &map) _settings.setValue(key, map.value(key)); } _settings.endGroup(); + _settings.sync(); } QVariantMap ImageWriter::getSavedCustomizationSettings() @@ -1060,10 +1061,12 @@ void ImageWriter::clearSavedCustomizationSettings() _settings.beginGroup("imagecustomization"); _settings.remove(""); _settings.endGroup(); + _settings.sync(); } bool ImageWriter::hasSavedCustomizationSettings() { + _settings.sync(); _settings.beginGroup("imagecustomization"); bool result = !_settings.childKeys().isEmpty(); _settings.endGroup(); diff --git a/src/main.qml b/src/main.qml index a3f6cbd..d755026 100644 --- a/src/main.qml +++ b/src/main.qml @@ -1183,6 +1183,10 @@ ApplicationWindow { OptionsPopup { id: optionspopup + onSaveSettingsSignal: { + imageWriter.setSavedCustomizationSettings(settings) + usesavedsettingspopup.hasSavedSettings = true + } } UseSavedSettingsPopup { @@ -1196,6 +1200,8 @@ ApplicationWindow { confirmwritepopup.askForConfirmation() } onNoClearSettings: { + hasSavedSettings = false + optionspopup.clearCustomizationFields() imageWriter.clearSavedCustomizationSettings() confirmwritepopup.askForConfirmation() }