Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/customization_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ QByteArray CustomisationGenerator::generateSystemdScript(const QVariantMap& s, c
bool hidden = s.value("wifiHidden").toBool();
if (!hidden)
hidden = s.value("wifiSSIDHidden").toBool();
const QString wifiCountry = s.value("wifiCountry").toString().trimmed();
const QString wifiCountry = s.value("recommendedWifiCountry").toString().trimmed();

// Prefer persisted crypted PSK; fallback to deriving from legacy plaintext setting
QString cryptedPsk = cryptedPskFromSettings;
Expand Down Expand Up @@ -372,7 +372,7 @@ QByteArray CustomisationGenerator::generateCloudInitUserData(const QVariantMap&
const bool piConnectEnabled = settings.value("piConnectEnabled").toBool();
QString cleanToken = piConnectToken.trimmed();
const QString ssid = settings.value("wifiSSID").toString();
const QString wifiCountry = settings.value("wifiCountry").toString().trimmed();
const QString wifiCountry = settings.value("recommendedWifiCountry").toString().trimmed();

// Determine if we need runcmd section
bool needsRuncmd = (piConnectEnabled && !cleanToken.isEmpty()) ||
Expand Down Expand Up @@ -422,7 +422,7 @@ QByteArray CustomisationGenerator::generateCloudInitNetworkConfig(const QVariant
const QString ssid = settings.value("wifiSSID").toString();
const QString cryptedPskFromSettings = settings.value("wifiPasswordCrypt").toString();
const bool hidden = settings.value("wifiHidden").toBool();
const QString regDom = settings.value("wifiCountry").toString().trimmed().toUpper();
const QString regDom = settings.value("recommendedWifiCountry").toString().trimmed().toUpper();

// Generate network config if we have a country code (regulatory domain) or an SSID
if (!regDom.isEmpty() || !ssid.isEmpty()) {
Expand Down
8 changes: 4 additions & 4 deletions src/imagewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1991,9 +1991,9 @@ void ImageWriter::_applySystemdCustomizationFromSettings(const QVariantMap &s)
// Use CustomisationGenerator for script generation
QByteArray script = rpi_imager::CustomisationGenerator::generateSystemdScript(s, _piConnectToken);

// Extract wifiCountry for cmdline append
// Extract recommendedWifiCountry for cmdline append
QByteArray cmdlineAppend;
const QString wifiCountry = s.value("wifiCountry").toString().trimmed();
const QString wifiCountry = s.value("recommendedWifiCountry").toString().trimmed();
if (!wifiCountry.isEmpty()) {
cmdlineAppend = QByteArray(" ") + QByteArray("cfg80211.ieee80211_regdom=") + wifiCountry.toUtf8();
}
Expand All @@ -2013,9 +2013,9 @@ void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s)
QByteArray netcfg = rpi_imager::CustomisationGenerator::generateCloudInitNetworkConfig(
s, hasCcRpi);

// Extract wifiCountry for cmdline append
// Extract recommendedWifiCountry for cmdline append
QByteArray cmdlineAppend;
const QString wifiCountry = s.value("wifiCountry").toString().trimmed();
const QString wifiCountry = s.value("recommendedWifiCountry").toString().trimmed();
if (!wifiCountry.isEmpty()) {
cmdlineAppend = QByteArray(" ") + QByteArray("cfg80211.ieee80211_regdom=") + wifiCountry.toUtf8();
}
Expand Down
18 changes: 9 additions & 9 deletions src/test/customization_generator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ TEST_CASE("CustomisationGenerator WiFi configuration", "[customization]") {
QVariantMap settings;
settings["wifiSSID"] = "TestNetwork";
settings["wifiPasswordCrypt"] = "hashed_password_here";
settings["wifiCountry"] = "GB";
settings["recommendedWifiCountry"] = "GB";
settings["wifiHidden"] = true;

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
Expand All @@ -235,7 +235,7 @@ TEST_CASE("CustomisationGenerator WiFi configuration with empty PSK", "[customiz
QVariantMap settings;
settings["wifiSSID"] = "OpenNetwork";
settings["wifiPasswordCrypt"] = ""; // Empty PSK for open network
settings["wifiCountry"] = "US";
settings["recommendedWifiCountry"] = "US";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand All @@ -249,7 +249,7 @@ TEST_CASE("CustomisationGenerator WiFi configuration with empty PSK", "[customiz
TEST_CASE("CustomisationGenerator WiFi country only (no SSID)", "[customization]") {
QVariantMap settings;
// Set country code GB without SSID - tests regulatory domain configuration
settings["wifiCountry"] = "GB";
settings["recommendedWifiCountry"] = "GB";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand Down Expand Up @@ -350,7 +350,7 @@ TEST_CASE("CustomisationGenerator handles special characters in WiFi SSID", "[cu
QVariantMap settings;
settings["wifiSSID"] = "Test Network (5GHz)";
settings["wifiPasswordCrypt"] = "fakehash";
settings["wifiCountry"] = "US";
settings["recommendedWifiCountry"] = "US";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand All @@ -364,7 +364,7 @@ TEST_CASE("CustomisationGenerator handles quotes in WiFi SSID", "[customization]
QVariantMap settings;
settings["wifiSSID"] = "My \"Quoted\" Network";
settings["wifiPasswordCrypt"] = "fakehash";
settings["wifiCountry"] = "US";
settings["recommendedWifiCountry"] = "US";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand All @@ -379,7 +379,7 @@ TEST_CASE("CustomisationGenerator handles backslashes in WiFi SSID", "[customiza
QVariantMap settings;
settings["wifiSSID"] = "Network\\With\\Backslashes";
settings["wifiPasswordCrypt"] = "fakehash";
settings["wifiCountry"] = "US";
settings["recommendedWifiCountry"] = "US";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand All @@ -392,7 +392,7 @@ TEST_CASE("CustomisationGenerator handles non-ASCII UTF-8 WiFi SSID", "[customiz
QVariantMap settings;
settings["wifiSSID"] = "Café ☕ 日本語";
settings["wifiPasswordCrypt"] = "fakehash"; // Pre-computed PSK (passwords are ASCII-only per WPA2 spec)
settings["wifiCountry"] = "FR";
settings["recommendedWifiCountry"] = "FR";

QByteArray script = CustomisationGenerator::generateSystemdScript(settings);
QString scriptStr = QString::fromUtf8(script);
Expand Down Expand Up @@ -610,7 +610,7 @@ TEST_CASE("CustomisationGenerator generates cloud-init network-config with WiFi"
QVariantMap settings;
settings["wifiSSID"] = "TestNetwork";
settings["wifiPasswordCrypt"] = "fakecryptedhash123";
settings["wifiCountry"] = "DE";
settings["recommendedWifiCountry"] = "DE";

QByteArray netcfg = CustomisationGenerator::generateCloudInitNetworkConfig(settings, false);
QString yaml = QString::fromUtf8(netcfg);
Expand Down Expand Up @@ -643,7 +643,7 @@ TEST_CASE("CustomisationGenerator generates cloud-init network-config with hidde
TEST_CASE("CustomisationGenerator cloud-init WiFi country only (no SSID)", "[cloudinit][network]") {
QVariantMap settings;
// Set country code FR without SSID - tests regulatory domain configuration
settings["wifiCountry"] = "FR";
settings["recommendedWifiCountry"] = "FR";

QByteArray userdata = CustomisationGenerator::generateCloudInitUserData(settings, "", false, false, "pi");
QString yaml = QString::fromUtf8(userdata);
Expand Down
113 changes: 3 additions & 110 deletions src/wizard/WifiCustomizationStep.qml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ WizardStepBase {
function ssidUnchanged(ssid, prev) { return (ssid || "") === (prev || "") }

title: qsTr("Customisation: Choose Wi‑Fi")
subtitle: qsTr("Configure wireless LAN settings")
showSkipButton: true

// Set initial focus on SSID
Expand All @@ -44,7 +43,6 @@ WizardStepBase {
if (confirmNeedsInput)
items.push(fieldWifiPasswordConfirm)
}
items.push(fieldWifiCountry)
return items
}, 1)
root.registerFocusGroup("wifi_options", function(){ return [chkWifiHidden] }, 2)
Expand All @@ -67,9 +65,6 @@ WizardStepBase {

// Set SSID placeholder after component is fully constructed (matches password field approach)
fieldWifiSSID.placeholderText = qsTr("Network name")

// Note: WiFi country is initialized by fieldWifiCountry's Component.onCompleted
// after the model is loaded, which properly handles recommended/saved/default values
if (saved.wifiHidden !== undefined) {
chkWifiHidden.checked = (saved.wifiHidden === true || saved.wifiHidden === "true")
}
Expand Down Expand Up @@ -328,90 +323,6 @@ WizardStepBase {
Layout.preferredHeight: pwdHintMetrics.height
}

WizardFormLabel {
text: qsTr("Wireless LAN country:")
}

ImComboBox {
id: fieldWifiCountry
Layout.fillWidth: true
model: []
font.pixelSize: Style.fontSizeInput
property bool isInitializing: true
Component.onCompleted: {
model = root.imageWriter.getCountryList()
// Always use recommended country from capital city selection
// Priority: recommendation from capital city > default (GB)
// We intentionally ignore any previously saved wifiCountry
var saved = root.imageWriter.getSavedCustomizationSettings()
console.log("WifiCustomizationStep: recommendedWifiCountry =", saved.recommendedWifiCountry)
if (saved && saved.recommendedWifiCountry && model && model.length > 0) {
// Use recommended country from capital city selection
var target = saved.recommendedWifiCountry
var idx = -1
for (var i = 0; i < model.length; i++) {
if (model[i] === target) { idx = i; break }
}
if (idx >= 0) {
currentIndex = idx
} else {
fieldWifiCountry.editText = target
}
} else if (model && model.length > 0) {
// Default to GB if available, else first item
var gbIndex = -1
for (var j = 0; j < model.length; j++) {
if (model[j] === "GB") { gbIndex = j; break }
}
currentIndex = (gbIndex >= 0) ? gbIndex : 0
}
isInitializing = false
// Now that initialization is complete, update the label once
recommendedLabel.updateVisibility()
}
onCurrentTextChanged: {
// Update visibility when selection changes (but not during initialization)
if (!isInitializing) {
recommendedLabel.updateVisibility()
}
}
onActiveFocusChanged: {
if (activeFocus)
wifiScroll.scrollToItem(this);
}
}

// Empty label to maintain grid alignment
Item { width: 1; height: 1 }

Text {
id: recommendedLabel
Layout.fillWidth: true
Layout.columnSpan: 1
color: "#4CAF50"
font.pixelSize: 11
wrapMode: Text.WordWrap

function updateVisibility() {
var saved = root.imageWriter.getSavedCustomizationSettings()
if (saved && saved.recommendedWifiCountry) {
var currentCountry = fieldWifiCountry.currentText || fieldWifiCountry.editText
visible = (currentCountry === saved.recommendedWifiCountry)
text = visible ? qsTr("✓ Recommended based on your capital city selection") : ""
console.log("WifiCustomizationStep: recommendation label visibility =", visible, "current =", currentCountry, "recommended =", saved.recommendedWifiCountry)
} else {
visible = false
text = ""
console.log("WifiCustomizationStep: no recommendation available")
}
}
}
}

RowLayout {
Layout.fillWidth: true
spacing: Style.spacingMedium

ImCheckBox {
id: chkWifiHidden
text: qsTr("Hidden SSID")
Expand All @@ -421,10 +332,6 @@ WizardStepBase {
wifiScroll.scrollToItem(this);
}
}

Item {
Layout.fillWidth: true
}
}
}
}
Expand Down Expand Up @@ -471,12 +378,11 @@ WizardStepBase {
}

// Validation: allow proceed when
// - SSID and country entered and either new PSK provided or a saved crypt exists; or
// - SSID entered and either new PSK provided or a saved crypt exists; or
// - all WiFi fields are empty (skip)
nextButtonEnabled: (function(){
var haveSSID = fieldWifiSSID.text && fieldWifiSSID.text.trim().length > 0
var haveCountry = (fieldWifiCountry.currentText || fieldWifiCountry.editText)
if (!haveSSID || !haveCountry) return true // allow skipping by leaving fields empty as before
if (!haveSSID) return true // allow skipping by leaving fields empty

if (wifiMode === "open") return true

Expand All @@ -503,7 +409,6 @@ WizardStepBase {
// Merge-and-save strategy
var saved = imageWriter.getSavedCustomizationSettings()
var ssid = fieldWifiSSID.text ? fieldWifiSSID.text.trim() : ""
var country = fieldWifiCountry.currentText || fieldWifiCountry.editText || ""
var pwd = fieldWifiPassword.text
var prevSSID = saved.wifiSSID || ""
var hidden = chkWifiHidden.checked
Expand All @@ -513,15 +418,6 @@ WizardStepBase {
// persist mode
saved.wifiMode = wifiMode

// Save country code if provided (even without SSID)
if (country.length > 0) {
saved.wifiCountry = country
wizardContainer.wifiConfigured = true
} else {
// No country -> clear country setting
delete saved.wifiCountry
}

// Handle SSID and password
if (ssid.length > 0) {
saved.wifiSSID = ssid
Expand Down Expand Up @@ -553,10 +449,7 @@ WizardStepBase {
delete saved.wifiSSID
delete saved.wifiPasswordCrypt
delete saved.wifiHidden
// If we have a country, still mark as configured
if (country.length === 0) {
wizardContainer.wifiConfigured = false
}
wizardContainer.wifiConfigured = false
}

imageWriter.setSavedCustomizationSettings(saved)
Expand Down