From b330185a8264631149f541a717ebe75c46a76943 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Mon, 29 Sep 2025 19:04:10 +0100 Subject: [PATCH] Prework for removing rpios cloud-init customization Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- src/CMakeLists.txt | 3 +- src/cli.cpp | 5 +- src/downloadthread.cpp | 5 +- src/downloadthread.h | 4 +- src/hwlistmodel.cpp | 1 - src/imageadvancedoptions.h | 20 -- src/imagewriter.cpp | 108 +----- src/imagewriter.h | 21 +- src/main.cpp | 9 - src/wizard/IfAndFeaturesCustomizationStep.qml | 333 ------------------ src/wizard/WizardContainer.qml | 78 +--- 11 files changed, 20 insertions(+), 567 deletions(-) delete mode 100644 src/imageadvancedoptions.h delete mode 100644 src/wizard/IfAndFeaturesCustomizationStep.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0fc13c9..e99bab8f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -162,7 +162,7 @@ set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelist oslistmodel.h disk_formatter.h file_operations.h platformquirks.h iconimageprovider.h - imageadvancedoptions.h + systemmemorymanager.h urlfmt.h ) @@ -426,7 +426,6 @@ if(NOT BUILD_CLI_ONLY) wizard/OSSelectionStep.qml wizard/StorageSelectionStep.qml wizard/HostnameCustomizationStep.qml - wizard/IfAndFeaturesCustomizationStep.qml wizard/LocaleCustomizationStep.qml wizard/UserCustomizationStep.qml wizard/WifiCustomizationStep.qml diff --git a/src/cli.cpp b/src/cli.cpp index ddc09dae..233d7be3 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -11,7 +11,6 @@ #include #include "drivelistmodel.h" #include "dependencies/drivelist/src/drivelist.hpp" -#include "imageadvancedoptions.h" /* Message handler to discard qDebug() output if using cli (unless --debug is set) */ static void devnullMsgHandler(QtMsgType, const QMessageLogContext &, const QString &) @@ -201,7 +200,7 @@ int Cli::run() return 1; } - _imageWriter->setImageCustomization("", "", "", userData, networkConfig, ImageOptions::NoAdvancedOptions); + _imageWriter->setImageCustomization("", "", "", userData, networkConfig); } else if (!parser.value("first-run-script").isEmpty()) { @@ -223,7 +222,7 @@ int Cli::run() return 1; } - _imageWriter->setImageCustomization("", "", firstRunScript, "", "", ImageOptions::UserDefinedFirstRun); + _imageWriter->setImageCustomization("", "", firstRunScript, "", ""); } _imageWriter->setDst(args[1]); diff --git a/src/downloadthread.cpp b/src/downloadthread.cpp index 6a74b891..2480f6b6 100644 --- a/src/downloadthread.cpp +++ b/src/downloadthread.cpp @@ -36,8 +36,6 @@ #include "windows/diskpart_util.h" #endif -#include "imageadvancedoptions.h" - #ifdef Q_OS_LINUX #include #include @@ -1133,7 +1131,7 @@ qint64 DownloadThread::_sectorsWritten() return -1; } -void DownloadThread::setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudInitNetwork, const QByteArray &initFormat, const ImageOptions::AdvancedOptions opts) +void DownloadThread::setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudInitNetwork, const QByteArray &initFormat) { _config = config; _cmdline = cmdline; @@ -1141,7 +1139,6 @@ void DownloadThread::setImageCustomization(const QByteArray &config, const QByte _cloudinit = cloudinit; _cloudinitNetwork = cloudInitNetwork; _initFormat = initFormat; - _advancedOptions = opts; } bool DownloadThread::_customizeImage() diff --git a/src/downloadthread.h b/src/downloadthread.h index 40992d1e..42f73455 100644 --- a/src/downloadthread.h +++ b/src/downloadthread.h @@ -18,7 +18,6 @@ #include #include #include "acceleratedcryptographichash.h" -#include "imageadvancedoptions.h" #include "systemmemorymanager.h" #include "file_operations.h" @@ -111,7 +110,7 @@ class DownloadThread : public QThread /* * Enable image customization */ - void setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork, const QByteArray &initFormat, const ImageOptions::AdvancedOptions opts); + void setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork, const QByteArray &initFormat); /* * Thread safe download progress query functions @@ -168,7 +167,6 @@ class DownloadThread : public QThread std::uint64_t _lastFailureOffset; qint64 _sectorsStart; QByteArray _url, _useragent, _buf, _filename, _lastError, _expectedHash, _config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat; - ImageOptions::AdvancedOptions _advancedOptions; char *_firstBlock; size_t _firstBlockSize; static QByteArray _proxy; diff --git a/src/hwlistmodel.cpp b/src/hwlistmodel.cpp index 6c7d74bb..606c2dc9 100644 --- a/src/hwlistmodel.cpp +++ b/src/hwlistmodel.cpp @@ -155,7 +155,6 @@ void HWListModel::setCurrentIndex(int index) { const HardwareDevice &device = _hwDevices.at(index); _imageWriter.setHWFilterList(device.tags, device.isInclusive()); - _imageWriter.setHWCapabilitiesList(device.capabilities); _imageWriter.setSrc({}); _currentIndex = index; diff --git a/src/imageadvancedoptions.h b/src/imageadvancedoptions.h deleted file mode 100644 index 9008c76c..00000000 --- a/src/imageadvancedoptions.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -namespace ImageOptions { -Q_NAMESPACE - -enum AdvancedOption { - NoAdvancedOptions = 0x0, - IsRpiosCloudInit = 0x1, - EnableSsh = 0x2, - UserDefinedFirstRun = 0x3, -}; -Q_ENUM_NS(AdvancedOption) - -Q_DECLARE_FLAGS(AdvancedOptions, AdvancedOption) -Q_FLAG_NS(AdvancedOptions) -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(ImageOptions::AdvancedOptions) diff --git a/src/imagewriter.cpp b/src/imagewriter.cpp index 83da74cc..9bec8517 100644 --- a/src/imagewriter.cpp +++ b/src/imagewriter.cpp @@ -51,7 +51,6 @@ #include #include #include -#include "imageadvancedoptions.h" #ifdef Q_OS_WIN #include @@ -62,8 +61,6 @@ #include "linux/stpanalyzer.h" #endif -using namespace ImageOptions; - namespace { constexpr uint MAX_SUBITEMS_DEPTH = 16; } // namespace anonymous @@ -608,7 +605,7 @@ void ImageWriter::startWrite() _thread->setVerifyEnabled(_verifyEnabled); _thread->setUserAgent(QString("Mozilla/5.0 rpi-imager/%1").arg(constantVersion()).toUtf8()); - _thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat, _advancedOptions); + _thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat); // Only set up cache operations for remote downloads, not when using cached files as source if (!_expectedHash.isEmpty() && !QUrl(urlstr).isLocalFile()) @@ -918,29 +915,6 @@ void ImageWriter::setHWFilterList(const QJsonArray &tags, const bool &inclusive) _deviceFilterIsInclusive = inclusive; } -void ImageWriter::setHWCapabilitiesList(const QJsonArray &json) { - // TODO: maybe also clear the sw capabilities as in the UI the OS is unselected when this changes - _hwCapabilities = json; -} - -static inline void pushLower(QStringList &dst, const QString &s) { - const QString t = s.trimmed().toLower(); - if (!t.isEmpty()) dst.push_back(t); -} - -void ImageWriter::setSWCapabilitiesList(const QString &json) { - _swCapabilities = QJsonArray{}; - QJsonParseError err{}; - const auto doc = QJsonDocument::fromJson(json.toUtf8(), &err); - if (err.error == QJsonParseError::NoError && doc.isArray()) { - _swCapabilities = doc.array(); - } else { - // optional CSV fallback ("a,b,c") - for (const auto &p : json.split(',', Qt::SkipEmptyParts)) - _swCapabilities.append(p.trimmed().toLower()); - } -} - QJsonArray ImageWriter::getHWFilterList() { return _deviceFilter; } @@ -949,21 +923,6 @@ bool ImageWriter::getHWFilterListInclusive() { return _deviceFilterIsInclusive; } -bool ImageWriter::checkHWAndSWCapability(const QString &cap, const QString &differentSWCap) { - return this->checkHWCapability(cap) && this->checkSWCapability(differentSWCap.isEmpty() ? cap : differentSWCap); -} - -bool ImageWriter::checkHWCapability(const QString &cap) { - return _hwCapabilities.contains(cap.trimmed().toLower()); -} - -bool ImageWriter::checkSWCapability(const QString &cap) { - const auto needle = cap.trimmed().toLower(); - for (const auto &v : _swCapabilities) - if (v.toString() == needle) return true; - return false; -} - void ImageWriter::handleNetworkRequestFinished(QNetworkReply *data) { // Defer deletion data->deleteLater(); @@ -1775,20 +1734,18 @@ void ImageWriter::setSetting(const QString &key, const QVariant &value) _settings.sync(); } -void ImageWriter::setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork, const ImageOptions::AdvancedOptions opts) +void ImageWriter::setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork) { _config = config; _cmdline = cmdline; _firstrun = firstrun; _cloudinit = cloudinit; _cloudinitNetwork = cloudinitNetwork; - _advancedOptions = opts; qDebug() << "Custom config.txt entries:" << config; qDebug() << "Custom cmdline.txt entries:" << cmdline; qDebug() << "Custom firstrun.sh:" << firstrun; qDebug() << "Cloudinit:" << cloudinit; - qDebug() << "Advanced options:" << opts; } void ImageWriter::applyCustomizationFromSavedSettings() @@ -1798,7 +1755,7 @@ void ImageWriter::applyCustomizationFromSavedSettings() // If the selected image does not support customization, ensure nothing is staged if (_initFormat.isEmpty()) { - setImageCustomization(QByteArray(), QByteArray(), QByteArray(), QByteArray(), QByteArray(), NoAdvancedOptions); + setImageCustomization(QByteArray(), QByteArray(), QByteArray(), QByteArray(), QByteArray()); return; } @@ -1997,7 +1954,7 @@ void ImageWriter::_applySystemdCustomizationFromSettings(const QVariantMap &s) line(QStringLiteral("sed -i 's| systemd.run.*||g' /boot/cmdline.txt"), script); line(QStringLiteral("exit 0"), script); - setImageCustomization(QByteArray(), cmdlineAppend, script, QByteArray(), QByteArray(), NoAdvancedOptions); + setImageCustomization(QByteArray(), cmdlineAppend, script, QByteArray(), QByteArray()); } void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s) @@ -2044,8 +2001,6 @@ void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s) const QString sshAuthorizedKeys = s.value("sshAuthorizedKeys").toString().trimmed(); if (sshEnabled) { - push(QStringLiteral("enable_ssh: true"), cloud); - if (!userName.isEmpty()) { push(QStringLiteral("users:"), cloud); // Parity: legacy QML used the typed username even when not renaming the user. @@ -2081,53 +2036,6 @@ void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s) } } - const bool isRpiosCloudInit = checkSWCapability("rpios_cloudinit"); - const bool enableI2C = s.value("enableI2C").toBool(); - const bool enableSPI = s.value("enableSPI").toBool(); - const QString enableSerial = s.value("enableSerial").toString(); - const bool armInterfaceEnabled = enableI2C || enableSPI || enableSerial != "Disabled"; - const bool isUsbGadgetEnabled = s.value("enableUsbGadget").toBool(); - - // cc_raspberry_pi config for rpios_cloudinit capable OSs - if (isRpiosCloudInit && (isUsbGadgetEnabled || armInterfaceEnabled)) { - push(QStringLiteral("rpi:"), cloud); - - if (isUsbGadgetEnabled) { - push(QStringLiteral(" enable_usb_gadget: true"), cloud); - } - - // configure arm interfaces - if (armInterfaceEnabled) { - push(QStringLiteral(" interfaces:"), cloud); - - if (enableI2C) { - push(QStringLiteral(" i2c: true"), cloud); - } - if (enableSPI) { - push(QStringLiteral(" spi: true"), cloud); - } - if (enableSerial != "Disabled") { - if (enableSerial == "" || enableSerial == "Default") { - push(QStringLiteral(" serial: true"), cloud); - } else { - push(QStringLiteral(" serial:"), cloud); - if (enableSerial == "Console & Hardware") { - push(QStringLiteral(" console: true"), cloud); - push(QStringLiteral(" hardware: true"), cloud); - } else if (enableSerial == "Console") { - push(QStringLiteral(" console: true"), cloud); - push(QStringLiteral(" hardware: false"), cloud); - } else if (enableSerial == "Hardware") { - push(QStringLiteral(" console: false"), cloud); - push(QStringLiteral(" hardware: true"), cloud); - } else { - qDebug() << "Invalid serial mode: " << enableSerial; - } - } - } - } - } - const QString ssid = s.value("wifiSSID").toString(); const QString cryptedPskFromSettings = s.value("wifiPasswordCrypt").toString(); const bool hidden = s.value("wifiHidden").toBool(); @@ -2141,8 +2049,8 @@ void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s) push(QStringLiteral(" version: 2"), netcfg); push(QStringLiteral(" wifis:"), netcfg); push(QStringLiteral(" renderer: %1") - .arg(isRpiosCloudInit ? QStringLiteral("NetworkManager") - : QStringLiteral("networkd")), + // TODO: maybe default to QStringLiteral("NetworkManager") for rpios based distros + .arg(QStringLiteral("networkd")), netcfg); push(QStringLiteral(" wlan0:"), netcfg); push(QStringLiteral(" dhcp4: true"), netcfg); @@ -2192,7 +2100,7 @@ void ImageWriter::_applyCloudInitCustomizationFromSettings(const QVariantMap &s) push(QStringLiteral(" - [ bash, -lc, \"install -o ") + effectiveUser + QStringLiteral(" -m 700 -d /home/") + effectiveUser + QStringLiteral("/com.raspberrypi.connect\" ]"), cloud); } - setImageCustomization(QByteArray(), cmdlineAppend, QByteArray(), cloud, netcfg, NoAdvancedOptions); + setImageCustomization(QByteArray(), cmdlineAppend, QByteArray(), cloud, netcfg); } QString ImageWriter::crypt(const QByteArray &password) @@ -2587,7 +2495,7 @@ void ImageWriter::_continueStartWriteAfterCacheVerification(bool cacheIsValid) _thread->setVerifyEnabled(_verifyEnabled); _thread->setUserAgent(QString("Mozilla/5.0 rpi-imager/%1").arg(constantVersion()).toUtf8()); - _thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat, _advancedOptions); + _thread->setImageCustomization(_config, _cmdline, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat); // Handle caching setup for downloads using CacheManager // Only set up caching when we're downloading (not using cached file as source) diff --git a/src/imagewriter.h b/src/imagewriter.h index e5b920ec..ba7482a9 100644 --- a/src/imagewriter.h +++ b/src/imagewriter.h @@ -27,7 +27,6 @@ #include "cachemanager.h" #include "device_info.h" #include "nativefiledialog.h" -#include "imageadvancedoptions.h" class QQmlApplicationEngine; class DownloadThread; @@ -144,27 +143,12 @@ class ImageWriter : public QObject /** Set the HW filter, for a filtered view of the OS list */ Q_INVOKABLE void setHWFilterList(const QJsonArray &tags, const bool &inclusive); - /* Set the capabilities supported by the hardware, for a filtered view of options that require the hardware to have certain capabilities. */ - Q_INVOKABLE void setHWCapabilitiesList(const QJsonArray &json); - - /* Set the capabilities supported by the hardware, for a filtered view of options that require the software to have certain capabilities. */ - Q_INVOKABLE void setSWCapabilitiesList(const QString &json); - /* Get the HW filter list */ Q_INVOKABLE QJsonArray getHWFilterList(); /* Get if the HW filter is in inclusive mode */ Q_INVOKABLE bool getHWFilterListInclusive(); - /* Get if both hard and software support a certain feature. If no differentSWCap is provided it will check for cap support in SW and HW lists. */ - Q_INVOKABLE bool checkHWAndSWCapability(const QString &cap, const QString &differentSWCap = ""); - - /* Check if the hardware supports a certain feature. */ - Q_INVOKABLE bool checkHWCapability(const QString &cap); - - /* Check if the software supports a certain feature. */ - Q_INVOKABLE bool checkSWCapability(const QString &cap); - /* Utility function to open OS file dialog */ Q_INVOKABLE void openFileDialog(const QString &title, const QString &filter); @@ -220,7 +204,7 @@ class ImageWriter : public QObject Q_INVOKABLE bool getBoolSetting(const QString &key); Q_INVOKABLE void setSetting(const QString &key, const QVariant &value); - Q_INVOKABLE void setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork, const ImageOptions::AdvancedOptions opts = {}); + Q_INVOKABLE void setImageCustomization(const QByteArray &config, const QByteArray &cmdline, const QByteArray &firstrun, const QByteArray &cloudinit, const QByteArray &cloudinitNetwork); Q_INVOKABLE void applyCustomizationFromSavedSettings(); Q_INVOKABLE void setSavedCustomizationSettings(const QVariantMap &map); Q_INVOKABLE QVariantMap getSavedCustomizationSettings(); @@ -311,7 +295,7 @@ protected slots: void fillSubLists(QJsonArray &topLevel); QNetworkAccessManager _networkManager; QJsonDocument _completeOsList; - QJsonArray _deviceFilter, _hwCapabilities, _swCapabilities; + QJsonArray _deviceFilter; bool _deviceFilterIsInclusive; std::shared_ptr _device_info; @@ -319,7 +303,6 @@ protected slots: QUrl _src, _repo; QString _dst, _parentCategory, _osName, _currentLang, _currentLangcode, _currentKeyboard; QByteArray _expectedHash, _cmdline, _config, _firstrun, _cloudinit, _cloudinitNetwork, _initFormat; - ImageOptions::AdvancedOptions _advancedOptions; quint64 _downloadLen, _extrLen, _devLen, _dlnow, _verifynow; DriveListModel _drivelist; bool _selectedDeviceValid; diff --git a/src/main.cpp b/src/main.cpp index 66e0bf4e..58b3b2bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,7 +34,6 @@ #include #include #endif -#include "imageadvancedoptions.h" static QTextStream cerr(stderr); @@ -105,14 +104,6 @@ int main(int argc, char *argv[]) app.setOrganizationDomain("raspberrypi.com"); app.setApplicationName("rpi-imager"); app.setWindowIcon(QIcon(":/icons/rpi-imager.ico")); - - qmlRegisterUncreatableMetaObject( - ImageOptions::staticMetaObject, // from Q_NAMESPACE - "ImageOptions", // import name in qml - 1, 0, // version - "ImageOptions", // QML type name - "Namespace only" - ); // Create ImageWriter early to check embedded mode ImageWriter imageWriter; diff --git a/src/wizard/IfAndFeaturesCustomizationStep.qml b/src/wizard/IfAndFeaturesCustomizationStep.qml deleted file mode 100644 index 2e778013..00000000 --- a/src/wizard/IfAndFeaturesCustomizationStep.qml +++ /dev/null @@ -1,333 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright (C) 2025 Raspberry Pi Ltd - */ - -import QtQuick 2.15 -import QtQuick.Layouts 1.15 -import QtQuick.Controls 2.15 -import QtQuick.Dialogs -import QtCore -import "../qmlcomponents" -import "components" - -import RpiImager - -WizardStepBase { - id: root - - required property ImageWriter imageWriter - required property var wizardContainer - - property bool supportsSerialConsoleOnly: false - property bool supportsUsbOtg: false - property bool isConfirmed: false - - title: qsTr("Customization: Interfaces & Features") - subtitle: qsTr("Enable hardware interfaces and connectivity options.") - showSkipButton: true - nextButtonEnabled: true - backButtonEnabled: true - - function updateCaps() { - // imageWriter knows the currently selected hardware - supportsSerialConsoleOnly = imageWriter.checkHWCapability("serial_on_console_only") - supportsUsbOtg = imageWriter.checkHWAndSWCapability("usb_otg") - } - - content: [ - ScrollView { - id: scroller - anchors.fill: parent - clip: true - ScrollBar.vertical.policy: ScrollBar.AsNeeded - ColumnLayout { - id: scrollContent - width: scroller.availableWidth - spacing: Style.stepContentSpacing - - // === Interfaces === - WizardSectionContainer { - ColumnLayout { - Layout.fillWidth: true - spacing: Style.spacingSmall - - // Section title - Label { - text: qsTr("Interfaces") - font.bold: true - font.pixelSize: Style.fontSizeTitle - Layout.alignment: Qt.AlignLeft - } - - // Interface toggles - ImOptionPill { - id: chkEnableI2C - Layout.fillWidth: true - text: qsTr("Enable I²C") - checked: false - } - - ImOptionPill { - id: chkEnableSPI - Layout.fillWidth: true - text: qsTr("Enable SPI") - checked: false - } - - RowLayout { - Layout.fillWidth: true - spacing: Style.spacingMedium - - WizardFormLabel { text: qsTr("Enable Serial:"); font.bold: true; Layout.fillWidth: true } - ImComboBox { - id: comboSerial - model: ListModel { - id: serialModel - ListElement { text: "Disabled" } - ListElement { text: "Default" } - ListElement { text: "Console & Hardware" } - ListElement { text: "Hardware" } - } - Layout.fillWidth: false - editable: false - selectTextByMouse: false - activeFocusOnTab: true - font.pixelSize: Style.fontSizeInput - Layout.alignment: Qt.AlignRight - } - } - } - } - - // === Features === - WizardSectionContainer { - ColumnLayout { - Layout.fillWidth: true - spacing: Style.spacingSmall - - // Section title - Label { - text: qsTr("Features") - font.bold: true - font.pixelSize: Style.fontSizeTitle - Layout.alignment: Qt.AlignLeft - } - - RowLayout { - Layout.fillWidth: true - visible: supportsUsbOtg - - ImOptionPill { - id: chkEnableUsbGadget - Layout.fillWidth: true - text: qsTr("Enable USB Gadget Mode") - helpLabel: imageWriter.isEmbeddedMode() ? "" : qsTr("Learn more about USB Gadget Mode") - helpUrl: imageWriter.isEmbeddedMode() ? "" : "https://www.raspberrypi.com/documentation/computers/usb-gadget.html" - checked: false - } - - Item { Layout.fillWidth: true } - } - } - } - } - } - ] - - Component.onCompleted: { - if (!imageWriter.checkSWCapability("rpios_cloudinit")) { - root.isConfirmed = true - wizardContainer.ifI2cEnabled = false - wizardContainer.ifSpiEnabled = false - wizardContainer.ifSerial = false - wizardContainer.featUsbGadgetEnabled = false - // skip page - wizardContainer.nextStep() - return - } - root.isConfirmed = false - - updateCaps() - - if (supportsSerialConsoleOnly) { - serialModel.append({ text: qsTr("Console") }) - } - - root.registerFocusGroup("if_section_interfaces", function() { - return [chkEnableI2C, chkEnableSPI, comboSerial] - }, 0) - - root.registerFocusGroup("if_section_features", function() { - return [chkEnableUsbGadget] - }, 1) - - // Prefill - var saved = imageWriter.getSavedCustomizationSettings() - // Load from persisted settings (if you store them there)… - chkEnableI2C.checked = saved.enableI2C === true || saved.enableI2C === "true" || wizardContainer.ifI2cEnabled - chkEnableSPI.checked = saved.enableSPI === true || saved.enableSPI === "true" || wizardContainer.ifSpiEnabled - var enableSerial = saved.enableSerial || wizardContainer.ifSerial - var idx = comboSerial.find(enableSerial) - comboSerial.currentIndex = (idx >= 0 ? idx : 0) - - // Features - if (supportsUsbOtg) { - chkEnableUsbGadget.checked = saved.enableUsbGadget === true || saved.enableUsbGadget === "true" || wizardContainer.featUsbGadgetEnabled - } else { - chkEnableUsbGadget.checked = false - } - } - - onNextClicked: { - let saved = imageWriter.getSavedCustomizationSettings() - - // Interfaces - saved.enableI2C = chkEnableI2C.checked - saved.enableSPI = chkEnableSPI.checked - saved.enableSerial = !supportsSerialConsoleOnly && comboSerial.editText === "Console" ? "Default" : comboSerial.editText - - // Features - saved.enableUsbGadget = supportsUsbOtg ? chkEnableUsbGadget.checked : false - - imageWriter.setSavedCustomizationSettings(saved) - - // Mirror into wizardContainer - wizardContainer.ifI2cEnabled = chkEnableI2C.checked - wizardContainer.ifSpiEnabled = chkEnableSPI.checked - wizardContainer.ifSerial = comboSerial.editText - wizardContainer.featUsbGadgetEnabled = saved.enableUsbGadget - - if (saved.enableUsbGadget && !wizardContainer.disableWarnings) { - confirmDialog.open() - } else { - root.isConfirmed = true - } - } - - // Confirmation dialog - Dialog { - id: confirmDialog - modal: true - parent: wizardContainer && wizardContainer.overlayRootRef ? wizardContainer.overlayRootRef : undefined - anchors.centerIn: parent - width: 520 - standardButtons: Dialog.NoButton - visible: false - - property bool allowAccept: false - title: qsTr("Enable USB Gadget Mode") - - background: Rectangle { - color: Style.mainBackgroundColor - radius: Style.sectionBorderRadius - border.color: Style.popupBorderColor - border.width: Style.sectionBorderWidth - } - - ColumnLayout { - anchors.fill: parent - anchors.margins: Style.cardPadding - spacing: Style.spacingMedium - - Text { - text: qsTr("USB Gadget Mode can change how your device behaves and may impact connectivity and host interaction.") - font.pixelSize: Style.fontSizeHeading - font.family: Style.fontFamilyBold - font.bold: true - color: Style.formLabelErrorColor - wrapMode: Text.WordWrap - Layout.fillWidth: true - } - - Text { - textFormat: Text.RichText - text: qsTr("Please review the documentation before proceeding.").arg(chkEnableUsbGadget.helpUrl) - font.pixelSize: Style.fontSizeFormLabel - font.family: Style.fontFamilyBold - color: Style.formLabelColor - wrapMode: Text.WordWrap - onLinkActivated: function(link) { Qt.openUrlExternally(link) } - Layout.fillWidth: true - } - - Text { - text: qsTr("Only continue if you are sure you know what you are doing.") - font.pixelSize: Style.fontSizeFormLabel - font.family: Style.fontFamilyBold - color: Style.formLabelErrorColor - wrapMode: Text.WordWrap - Layout.fillWidth: true - } - - RowLayout { - Layout.fillWidth: true - spacing: Style.spacingMedium - Item { Layout.fillWidth: true } - - ImButton { - text: qsTr("Cancel") - onClicked: confirmDialog.close() - } - - ImButtonRed { - id: acceptBtn - text: qsTr("I understand, continue") - onClicked: { - confirmDialog.close() - root.isConfirmed = true - // Advance to next step - wizardContainer.nextStep() - } - } - } - } - - // Delay accept for 2 seconds - Timer { - id: confirmDelay - interval: 2000 - running: false - repeat: false - onTriggered: confirmDialog.allowAccept = true - } - - // Ensure disabled before showing to avoid flicker - onAboutToShow: { - allowAccept = false - confirmDelay.start() - } - onClosed: { - confirmDelay.stop() - allowAccept = false - } - } - - onSkipClicked: { - // Clear all customization flags - wizardContainer.hostnameConfigured = false - wizardContainer.localeConfigured = false - wizardContainer.userConfigured = false - wizardContainer.wifiConfigured = false - wizardContainer.sshEnabled = false - wizardContainer.piConnectEnabled = false - wizardContainer.ifI2cEnabled = false - wizardContainer.ifSpiEnabled = false - wizardContainer.ifSerial = "Disabled" - wizardContainer.featUsbGadgetEnabled = false - - // Jump to writing step - wizardContainer.jumpToStep(wizardContainer.stepWriting) - } - - Connections { - // Recompute caps if the selected device changes elsewhere - target: wizardContainer - function onSelectedDeviceNameChanged() { - updateCaps() - // If Console is no longer supported and was selected, fall back - if (!supportsSerialConsoleOnly && comboSerial.editText === qsTr("Console")) - comboSerial.currentIndex = 0; - } - } -} diff --git a/src/wizard/WizardContainer.qml b/src/wizard/WizardContainer.qml index 40b64097..73c39000 100644 --- a/src/wizard/WizardContainer.qml +++ b/src/wizard/WizardContainer.qml @@ -24,7 +24,7 @@ Item { property alias networkInfoText: networkInfo.text property int currentStep: 0 - readonly property int totalSteps: 12 + readonly property int totalSteps: 11 // Track which steps have been made permissible/unlocked for navigation // Each bit represents a step: bit 0 = Device, bit 1 = OS, etc. @@ -41,9 +41,6 @@ Item { // Track previous selections to detect changes property string previousDeviceName: "" property string previousOsName: "" - - property bool supportsSerialConsoleOnly: false - property bool supportsUsbGadget: false // Track customizations that were actually configured property bool hostnameConfigured: false @@ -55,14 +52,6 @@ Item { // Whether selected OS supports Raspberry Raspberry Pi Connect customization property bool piConnectAvailable: false - // Interfaces & Features - property bool rpiosCloudInitAvailable: false - property bool ifI2cEnabled: false - property bool ifSpiEnabled: false - // "Disabled" | "Default" | "Console & Hardware" | "Console" | "Hardware" | "" - property string ifSerial: "" - property bool featUsbGadgetEnabled: false - // Ephemeral per-run setting: do not persist across runs property bool disableWarnings: false // Whether the selected OS supports customisation (init_format present) @@ -78,9 +67,8 @@ Item { readonly property int stepWifiCustomization: 6 readonly property int stepRemoteAccess: 7 readonly property int stepPiConnectCustomization: 8 - readonly property int stepIfAndFeatures: 9 - readonly property int stepWriting: 10 - readonly property int stepDone: 11 + readonly property int stepWriting: 9 + readonly property int stepDone: 10 signal wizardCompleted() @@ -143,9 +131,7 @@ Item { } function getLastCustomizationStep() { - return rpiosCloudInitAvailable - ? stepIfAndFeatures - : piConnectAvailable + return piConnectAvailable ? stepPiConnectCustomization : stepRemoteAccess } @@ -160,9 +146,6 @@ Item { if (piConnectAvailable) { labels.push(qsTr("Raspberry Pi Connect")) } - if (rpiosCloudInitAvailable) { - labels.push(qsTr("Interfaces & Features")) - } return labels } @@ -218,11 +201,6 @@ Item { sshEnabled = false piConnectEnabled = false piConnectAvailable = false - rpiosCloudInitAvailable = false - ifI2cEnabled = false - ifSpiEnabled = false - ifSerial = "" - featUsbGadgetEnabled = false } function invalidateOSDependentSteps() { @@ -244,11 +222,6 @@ Item { // Reset OS capability flags - these will be set correctly by OS selection piConnectAvailable = false - rpiosCloudInitAvailable = false - ifI2cEnabled = false - ifSpiEnabled = false - ifSerial = "" - featUsbGadgetEnabled = false } @@ -428,7 +401,6 @@ Item { else if (root.currentStep === root.stepWifiCustomization) currentStepLabel = qsTr("Wi‑Fi") else if (root.currentStep === root.stepRemoteAccess) currentStepLabel = qsTr("Remote Access") else if (root.currentStep === root.stepPiConnectCustomization) currentStepLabel = qsTr("Raspberry Pi Connect") - else if (root.currentStep === root.stepIfAndFeatures) currentStepLabel = qsTr("Interfaces & Features") return labels[subItem.index] === currentStepLabel } @@ -445,8 +417,7 @@ Item { root.isStepPermissible(root.stepUserCustomization) || root.isStepPermissible(root.stepWifiCustomization) || root.isStepPermissible(root.stepRemoteAccess) || - root.isStepPermissible(root.stepPiConnectCustomization) || - root.isStepPermissible(root.stepIfAndFeatures) + root.isStepPermissible(root.stepPiConnectCustomization) ) MouseArea { @@ -468,7 +439,6 @@ Item { else if (stepLabel === qsTr("Wi‑Fi")) target = root.stepWifiCustomization else if (stepLabel === qsTr("Remote Access")) target = root.stepRemoteAccess else if (stepLabel === qsTr("Raspberry Pi Connect")) target = root.stepPiConnectCustomization - else if (stepLabel === qsTr("Interfaces & Features")) target = root.stepIfAndFeatures // Allow navigation to permissible steps or backward navigation within customization if (root.currentStep !== target && (root.isStepPermissible(target) || target < root.currentStep)) { @@ -670,10 +640,6 @@ Item { if (!piConnectAvailable && nextIndex === stepPiConnectCustomization) { nextIndex++ } - // skip interfaces and features for Operating Systems that don't have the cap rpios_cloudinit - if (!rpiosCloudInitAvailable && nextIndex == stepIfAndFeatures) { - nextIndex++ - } // Before entering the writing step, persist and apply customization (when supported) if (nextIndex === stepWriting && customizationSupported && imageWriter) { // Persist whatever is currently staged in per-step UIs @@ -701,10 +667,6 @@ Item { if (root.currentStep === stepWriting && !customizationSupported) { prevIndex = stepStorageSelection } else { - // skip interfaces and features for Operating Systems that don't have the cap rpios_cloudinit - if (prevIndex == stepIfAndFeatures && !rpiosCloudInitAvailable) { - prevIndex-- - } if (prevIndex === stepPiConnectCustomization && !piConnectAvailable) { prevIndex-- } @@ -742,7 +704,6 @@ Item { case stepWifiCustomization: return wifiCustomizationStep case stepRemoteAccess: return remoteAccessStep case stepPiConnectCustomization: return piConnectCustomizationStep - case stepIfAndFeatures: return ifAndFeaturesStep case stepWriting: return writingStep case stepDone: return doneStep default: return null @@ -878,26 +839,6 @@ Item { } } } - - Component { - id: ifAndFeaturesStep - IfAndFeaturesCustomizationStep { - imageWriter: root.imageWriter - wizardContainer: root - appOptionsButton: optionsButton - onNextClicked: { - // Only advance if the step indicates it's ready - if (isConfirmed) { - root.nextStep() - } - // Otherwise, let the step handle the action internally - } - onBackClicked: root.previousStep() - onSkipClicked: { - // Skip functionality is handled in the step itself - } - } - } Component { id: writingStep @@ -975,15 +916,6 @@ Item { sshEnabled = false piConnectEnabled = false piConnectAvailable = false - - rpiosCloudInitAvailable = false - ifI2cEnabled = false - ifSpiEnabled = false - ifSerial = "" - featUsbGadgetEnabled = false - - supportsSerialConsoleOnly = false - supportsUsbGadget = false // Navigate back to the first step wizardStack.clear()