diff --git a/src/app/drivemanager.cpp b/src/app/drivemanager.cpp index 0ad1cb34..085d11f2 100644 --- a/src/app/drivemanager.cpp +++ b/src/app/drivemanager.cpp @@ -122,10 +122,27 @@ int DriveManager::length() const return m_drives.count(); } -Drive *DriveManager::lastRestoreable() +int DriveManager::restoreableCount() const { - return m_lastRestoreable; + return m_restoreableDrives.count(); } + +QVariantList DriveManager::restoreableDrives() const +{ + QVariantList list; + for (auto d : m_restoreableDrives) { + list.append(QVariant::fromValue(d)); + } + return list; +} + +Drive *DriveManager::restoreableDriveAt(int index) const +{ + if (index >= 0 && index < m_restoreableDrives.count()) + return m_restoreableDrives[index]; + return nullptr; +} + bool DriveManager::isBackendBroken() { return !m_errorString.isEmpty(); @@ -136,14 +153,6 @@ QString DriveManager::errorString() return m_errorString; } -void DriveManager::setLastRestoreable(Drive *d) -{ - if (m_lastRestoreable != d) { - m_lastRestoreable = d; - emit restoreableDriveChanged(); - } -} - void DriveManager::onDriveConnected(Drive *d) { int position = 0; @@ -165,13 +174,11 @@ void DriveManager::onDriveConnected(Drive *d) emit selectedChanged(); } - if (d->restoreStatus() == Drive::CONTAINS_LIVE) { - setLastRestoreable(d); - connect(d, &Drive::restoreStatusChanged, [=]() { - if (d && d == m_lastRestoreable && d->restoreStatus() != Drive::CONTAINS_LIVE) - setLastRestoreable(nullptr); - }); - } + // Connect to restoreStatus changes for updating the restorable list + connect(d, &Drive::restoreStatusChanged, this, &DriveManager::onDriveRestoreStatusChanged); + + // Update restorable drives list + updateRestoreableDrives(); } void DriveManager::onDriveRemoved(Drive *d) @@ -186,11 +193,10 @@ void DriveManager::onDriveRemoved(Drive *d) m_selectedIndex = 0; } emit selectedChanged(); - - if (d == m_lastRestoreable) { - setLastRestoreable(nullptr); - } } + + // Update restorable drives list + updateRestoreableDrives(); } void DriveManager::onBackendBroken(const QString &message) @@ -199,6 +205,26 @@ void DriveManager::onBackendBroken(const QString &message) emit isBackendBrokenChanged(); } +void DriveManager::onDriveRestoreStatusChanged() +{ + updateRestoreableDrives(); +} + +void DriveManager::updateRestoreableDrives() +{ + QList newList; + for (auto d : m_drives) { + if (d->restoreStatus() == Drive::CONTAINS_LIVE) { + newList.append(d); + } + } + + if (newList != m_restoreableDrives) { + m_restoreableDrives = newList; + emit restoreableDrivesChanged(); + } +} + DriveProvider *DriveProvider::create(DriveManager *parent) { if (options.testing) diff --git a/src/app/drivemanager.h b/src/app/drivemanager.h index 4e1d396c..54a5bdba 100644 --- a/src/app/drivemanager.h +++ b/src/app/drivemanager.h @@ -22,6 +22,7 @@ #include #include +#include #include "releasemanager.h" @@ -40,7 +41,7 @@ class UdisksDrive; * @property length count of the drives * @property selected the selected drive * @property selectedIndex the index of the selected drive - * @property lastRestoreable the most recently connected restoreable drive + * @property restoreableCount count of drives containing live USB */ class DriveManager : public QAbstractListModel { @@ -51,7 +52,8 @@ class DriveManager : public QAbstractListModel Q_PROPERTY(bool isBroken READ isBackendBroken NOTIFY isBackendBrokenChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY isBackendBrokenChanged) - Q_PROPERTY(Drive *lastRestoreable READ lastRestoreable WRITE setLastRestoreable NOTIFY restoreableDriveChanged) + Q_PROPERTY(int restoreableCount READ restoreableCount NOTIFY restoreableDrivesChanged) + Q_PROPERTY(QVariantList restoreableDrives READ restoreableDrives NOTIFY restoreableDrivesChanged) public: static DriveManager *instance(); @@ -66,31 +68,33 @@ class DriveManager : public QAbstractListModel int length() const; - Drive *lastRestoreable(); + int restoreableCount() const; + QVariantList restoreableDrives() const; + Q_INVOKABLE Drive *restoreableDriveAt(int index) const; bool isBackendBroken(); QString errorString(); - void setLastRestoreable(Drive *d); - private slots: void onDriveConnected(Drive *d); void onDriveRemoved(Drive *d); void onBackendBroken(const QString &message); + void onDriveRestoreStatusChanged(); signals: void drivesChanged(); void selectedChanged(); - void restoreableDriveChanged(); + void restoreableDrivesChanged(); void isBackendBrokenChanged(); private: explicit DriveManager(QObject *parent = 0); + void updateRestoreableDrives(); static DriveManager *_self; QList m_drives{}; + QList m_restoreableDrives{}; int m_selectedIndex{0}; - Drive *m_lastRestoreable{nullptr}; DriveProvider *m_provider{nullptr}; QString m_errorString{}; }; diff --git a/src/app/qml/MainPage.qml b/src/app/qml/MainPage.qml index e0f54e11..2ad86905 100644 --- a/src/app/qml/MainPage.qml +++ b/src/app/qml/MainPage.qml @@ -46,18 +46,23 @@ Page { QQC2.RadioButton { id: restoreRadio - visible: drives.lastRestoreable - text: drives.lastRestoreable ? qsTr("Restore %1").arg(drives.lastRestoreable.name) : "" + visible: drives.restoreableCount + text: { + if (drives.restoreableCount === 1) + return qsTr("Restore %1").arg(drives.restoreableDriveAt(0).name) + else + return qsTr("Restore a USB drive (%1 available)").arg(drives.restoreableCount) + } onClicked: { selectedOption = Units.MainSelect.Restore } Connections { target: drives - function onLastRestoreableChanged() { - if (drives.lastRestoreable != null && !restoreRadio.visible) + function onRestoreableDrivesChanged() { + if (drives.restoreableCount && !restoreRadio.visible) restoreRadio.visible = true - if (!drives.lastRestoreable) + if (!drives.restoreableCount) restoreRadio.visible = false } } diff --git a/src/app/qml/RestorePage.qml b/src/app/qml/RestorePage.qml index b98ce448..26f9c7b2 100644 --- a/src/app/qml/RestorePage.qml +++ b/src/app/qml/RestorePage.qml @@ -25,12 +25,36 @@ import QtQuick.Layouts 6.6 Page { id: restorePage - text: qsTr("Restore Drive %1").arg(lastRestoreable.name) + property var selectedDrive: drives.restoreableCount > 0 ? drives.restoreableDriveAt(driveCombo.currentIndex) : null + property var restoringDrive: null + + text: qsTr("Restore Drive %1").arg(restoringDrive ? restoringDrive.name : (selectedDrive ? selectedDrive.name : "")) textLevel: 1 + ColumnLayout { + id: driveSelectionColumn + visible: drives.restoreableCount > 0 && !restoringDrive + Layout.fillWidth: true + + QQC2.Label { + text: qsTr("Select USB Drive to Restore:") + font.bold: true + } + + QQC2.ComboBox { + id: driveCombo + Layout.fillWidth: true + model: drives.restoreableDrives + enabled: drives.restoreableCount > 0 + visible: drives.restoreableCount > 0 + currentIndex: 0 + textRole: "name" + } + } + QQC2.Label { id: warningText - visible: lastRestoreable.restoreStatus == Units.RestoreStatus.Contains_Live + visible: selectedDrive && selectedDrive.restoreStatus == Units.RestoreStatus.Contains_Live && !restoringDrive Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true text: qsTr("

To reclaim all space available on the drive, it has to be restored to its factory settings. The live system and all saved data will be deleted.

You don't need to restore the drive if you want to write another live system to it.

Do you want to restore it to factory settings?

" ) @@ -40,7 +64,7 @@ Page { ColumnLayout { id: progress - visible: lastRestoreable.restoreStatus == Units.RestoreStatus.Restoring + visible: restoringDrive && restoringDrive.restoreStatus == Units.RestoreStatus.Restoring Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true @@ -63,7 +87,7 @@ Page { QQC2.Label { id: restoredText - visible: lastRestoreable.restoreStatus == Units.RestoreStatus.Restored + visible: restoringDrive && restoringDrive.restoreStatus == Units.RestoreStatus.Restored Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true text: qsTr("Your drive was successfully restored!") @@ -72,47 +96,47 @@ Page { QQC2.Label { id: errorText - visible: lastRestoreable.restoreStatus == Units.RestoreStatus.Restore_Error + visible: restoringDrive && restoringDrive.restoreStatus == Units.RestoreStatus.Restore_Error Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true text: qsTr("Unfortunately, an error occurred during the process. Please try restoring the drive using your system tools.") wrapMode: QQC2.Label.Wrap } - - Component.onCompleted: { - lastRestoreable = drives.lastRestoreable - } - + states: [ State { name: "restored" - when: lastRestoreable.restoreStatus == Units.RestoreStatus.Restored + when: restoringDrive && restoringDrive.restoreStatus == Units.RestoreStatus.Restored PropertyChanges { target: mainWindow; title: qsTr("Restoring finished") } - StateChangeScript { - script: drives.lastRestoreable = null - } } ] - previousButtonEnabled: lastRestoreable.restoreStatus != Units.RestoreStatus.Restored && - lastRestoreable.restoreStatus != Units.RestoreStatus.Restoring + previousButtonEnabled: !restoringDrive || (restoringDrive.restoreStatus != Units.RestoreStatus.Restoring && restoringDrive.restoreStatus != Units.RestoreStatus.Restored) previousButtonVisible: previousButtonEnabled onPreviousButtonClicked: { + restoringDrive = null selectedPage = Units.Page.MainPage } - nextButtonEnabled: lastRestoreable.restoreStatus == Units.RestoreStatus.Restored || - lastRestoreable.restoreStatus == Units.RestoreStatus.Contains_Live - nextButtonVisible: lastRestoreable.restoreStatus != Units.RestoreStatus.Restoring - nextButtonText: lastRestoreable.restoreStatus == Units.RestoreStatus.Restored ? qsTr("Finish") : qsTr("Restore") + nextButtonEnabled: { + if (restoringDrive) { + return restoringDrive.restoreStatus == Units.RestoreStatus.Restored || + restoringDrive.restoreStatus == Units.RestoreStatus.Restore_Error + } + return selectedDrive && selectedDrive.restoreStatus == Units.RestoreStatus.Contains_Live + } + nextButtonVisible: !restoringDrive || restoringDrive.restoreStatus != Units.RestoreStatus.Restoring + nextButtonText: restoringDrive && (restoringDrive.restoreStatus == Units.RestoreStatus.Restored || restoringDrive.restoreStatus == Units.RestoreStatus.Restore_Error) ? qsTr("Finish") : qsTr("Restore") onNextButtonClicked: { - if (lastRestoreable.restoreStatus == Units.RestoreStatus.Restored) + if (restoringDrive && (restoringDrive.restoreStatus == Units.RestoreStatus.Restored || restoringDrive.restoreStatus == Units.RestoreStatus.Restore_Error)) { + restoringDrive = null selectedPage = Units.Page.MainPage - else - drives.lastRestoreable.restore() + } else if (selectedDrive) { + restoringDrive = selectedDrive + restoringDrive.restore() + } } - } diff --git a/src/app/qml/main.qml b/src/app/qml/main.qml index c0ba08c4..15358ad9 100644 --- a/src/app/qml/main.qml +++ b/src/app/qml/main.qml @@ -31,7 +31,6 @@ ApplicationWindow { property int selectedPage: Units.Page.MainPage property int selectedVersion: Units.Source.Product property int selectedOption: Units.MainSelect.Download - property QtObject lastRestoreable property bool eraseVariant: false StackView { @@ -144,14 +143,6 @@ ApplicationWindow { } ] } - - Connections { - target: drives - function onLastRestoreableChanged() { - if (!drives.selected) - selectedPage = Units.Page.MainPage - } - } Units { id: units