2023-04-14 19:31:10 +03:00
|
|
|
import QtQuick
|
|
|
|
|
import QtQuick.Controls
|
|
|
|
|
import QtQuick.Layouts
|
|
|
|
|
|
2023-05-22 00:10:51 +08:00
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
|
|
2023-04-14 19:31:10 +03:00
|
|
|
import PageEnum 1.0
|
2023-05-22 00:10:51 +08:00
|
|
|
import ContainerProps 1.0
|
|
|
|
|
import ProtocolProps 1.0
|
2024-07-07 13:42:38 +03:00
|
|
|
import Style 1.0
|
2023-04-14 19:31:10 +03:00
|
|
|
|
|
|
|
|
import "./"
|
|
|
|
|
import "../Controls2"
|
|
|
|
|
import "../Config"
|
|
|
|
|
|
2023-05-25 15:40:17 +08:00
|
|
|
PageType {
|
2023-04-14 19:31:10 +03:00
|
|
|
id: root
|
2026-02-04 23:03:38 +03:00
|
|
|
objectName: "pageSetupWizardEasy"
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2023-07-31 20:38:13 +09:00
|
|
|
property bool isEasySetup: true
|
2026-02-04 23:03:38 +03:00
|
|
|
property bool isRestoreFromBackup: false
|
|
|
|
|
property string backupFilePath: ""
|
|
|
|
|
property string restoreHostname: ""
|
|
|
|
|
property string restoreUsername: ""
|
|
|
|
|
property string restoreSecretData: ""
|
|
|
|
|
property bool waitingForServerToAdd: false
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// For installing containers from backup
|
2026-02-05 10:29:18 +03:00
|
|
|
property var containersToInstall: []
|
|
|
|
|
property int currentContainerIndex: 0
|
|
|
|
|
property bool isInstallingContainers: false
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Connections for ServersBackupController
|
|
|
|
|
Connections {
|
|
|
|
|
target: ServersBackupController
|
|
|
|
|
|
|
|
|
|
function onReadyForRestore(backupFilePath, hostname, username, secretData, serverIp, fileName) {
|
|
|
|
|
console.log("onReadyForRestore received from C++")
|
|
|
|
|
console.log(" backupFilePath:", backupFilePath)
|
|
|
|
|
console.log(" hostname:", hostname)
|
|
|
|
|
console.log(" serverIp:", serverIp)
|
|
|
|
|
console.log(" fileName:", fileName)
|
|
|
|
|
|
|
|
|
|
// Scan backup to determine containers (C++ already did this, but needed for QML)
|
|
|
|
|
var foundContainers = ServersBackupController.scanBackupForContainers(backupFilePath)
|
|
|
|
|
console.log("Found containers:", foundContainers)
|
|
|
|
|
|
|
|
|
|
if (foundContainers.length === 0) {
|
|
|
|
|
PageController.showErrorMessage(qsTr("No containers found in backup file"))
|
|
|
|
|
root.isRestoreFromBackup = false
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
root.containersToInstall = foundContainers
|
|
|
|
|
root.currentContainerIndex = 0
|
|
|
|
|
|
|
|
|
|
// Now add empty server with these credentials
|
|
|
|
|
InstallController.setProcessedServerCredentials(hostname, username, secretData)
|
|
|
|
|
|
|
|
|
|
// Set waiting flag
|
|
|
|
|
root.waitingForServerToAdd = true
|
|
|
|
|
|
|
|
|
|
console.log("Backup scanned, adding server...")
|
|
|
|
|
// Add server (asynchronously)
|
|
|
|
|
InstallController.addEmptyServer()
|
|
|
|
|
|
|
|
|
|
// Further execution will happen in onInstallServerFinished
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connections for tracking server addition
|
2026-02-04 23:03:38 +03:00
|
|
|
Connections {
|
|
|
|
|
target: InstallController
|
|
|
|
|
|
|
|
|
|
function onInstallServerFinished(finishedMessage) {
|
|
|
|
|
if (root.waitingForServerToAdd && root.isRestoreFromBackup && root.backupFilePath.length > 0) {
|
2026-02-05 10:29:18 +03:00
|
|
|
console.log("Server added successfully, now installing containers from backup...")
|
2026-02-04 23:03:38 +03:00
|
|
|
root.waitingForServerToAdd = false
|
2026-05-29 14:32:29 +03:00
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Start installing containers
|
2026-02-05 10:29:18 +03:00
|
|
|
root.isInstallingContainers = true
|
|
|
|
|
installNextContainer()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
|
|
|
|
if (root.isInstallingContainers) {
|
|
|
|
|
console.log("Container installed:", finishedMessage)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Move to next container
|
2026-02-05 10:29:18 +03:00
|
|
|
root.currentContainerIndex++
|
|
|
|
|
|
|
|
|
|
if (root.currentContainerIndex < root.containersToInstall.length) {
|
2026-02-06 17:14:08 +03:00
|
|
|
// Install next container
|
2026-02-05 10:29:18 +03:00
|
|
|
installNextContainer()
|
|
|
|
|
} else {
|
2026-02-06 17:14:08 +03:00
|
|
|
// All containers installed, now do restore
|
2026-02-05 10:29:18 +03:00
|
|
|
console.log("All containers installed, starting restore...")
|
|
|
|
|
root.isInstallingContainers = false
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// IMPORTANT: Turn off busy indicator before navigation
|
2026-02-05 10:29:18 +03:00
|
|
|
PageController.showBusyIndicator(false)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Start navigation to restore mode selection page
|
2026-02-05 10:29:18 +03:00
|
|
|
navigationTimer.start()
|
|
|
|
|
}
|
2026-02-04 23:03:38 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Function to install next container from list
|
2026-02-05 10:29:18 +03:00
|
|
|
function installNextContainer() {
|
|
|
|
|
if (root.currentContainerIndex >= root.containersToInstall.length) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var containerName = root.containersToInstall[root.currentContainerIndex]
|
|
|
|
|
console.log("Installing container:", containerName, "(", root.currentContainerIndex + 1, "/", root.containersToInstall.length, ")")
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Convert container name to DockerContainer enum
|
2026-02-05 10:29:18 +03:00
|
|
|
var dockerContainer = ContainerProps.containerFromString(containerName)
|
|
|
|
|
|
|
|
|
|
if (dockerContainer === 0) { // None
|
|
|
|
|
console.log("Unknown container:", containerName, "skipping...")
|
|
|
|
|
root.currentContainerIndex++
|
|
|
|
|
installNextContainer()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Get default settings for container
|
2026-02-05 10:29:18 +03:00
|
|
|
var defaultProtocol = ContainerProps.defaultProtocol(dockerContainer)
|
2026-05-29 14:32:29 +03:00
|
|
|
var defaultPort = InstallController.getPortForInstall(defaultProtocol)
|
|
|
|
|
var defaultTransport = InstallController.defaultTransportProto(defaultProtocol)
|
|
|
|
|
|
|
|
|
|
// Set server index
|
|
|
|
|
var serverIdx = ServersModel.getServersCount() - 1
|
|
|
|
|
ServersModel.processedIndex = serverIdx
|
|
|
|
|
var serverId = ServersUiController.getServerId(serverIdx)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Show loading indicator with message
|
2026-02-05 10:29:18 +03:00
|
|
|
PageController.showBusyIndicator(true)
|
|
|
|
|
PageController.showNotificationMessage(qsTr("Installing %1 (%2/%3)...")
|
|
|
|
|
.arg(containerName)
|
|
|
|
|
.arg(root.currentContainerIndex + 1)
|
|
|
|
|
.arg(root.containersToInstall.length))
|
2026-05-29 14:32:29 +03:00
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Ensure credentials are set
|
2026-02-05 10:29:18 +03:00
|
|
|
InstallController.setProcessedServerCredentials(root.restoreHostname, root.restoreUsername, root.restoreSecretData)
|
2026-05-29 14:32:29 +03:00
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Install container
|
2026-05-29 14:32:29 +03:00
|
|
|
console.log("Installing container:", containerName, "serverId:", serverId)
|
2026-02-05 10:29:18 +03:00
|
|
|
ContainersModel.setProcessedContainerIndex(dockerContainer)
|
2026-05-29 14:32:29 +03:00
|
|
|
InstallController.install(dockerContainer, defaultPort, defaultTransport, serverId)
|
2026-02-05 10:29:18 +03:00
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Timer for navigating to restore mode selection page after file selection
|
2026-02-04 23:03:38 +03:00
|
|
|
Timer {
|
|
|
|
|
id: navigationTimer
|
|
|
|
|
interval: 500
|
|
|
|
|
repeat: false
|
|
|
|
|
onTriggered: {
|
|
|
|
|
if (root.backupFilePath.length > 0 && root.isRestoreFromBackup) {
|
|
|
|
|
console.log("Navigation timer triggered, going to restore mode page")
|
|
|
|
|
console.log("Credentials available:", root.restoreHostname, root.restoreUsername, root.restoreSecretData.length > 0 ? "***" : "EMPTY")
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Get filename
|
2026-02-04 23:03:38 +03:00
|
|
|
var fileName = SystemController.getFileNameFromPath(root.backupFilePath)
|
|
|
|
|
if (!fileName || fileName === undefined || fileName.length === 0) {
|
|
|
|
|
var fallbackName = root.backupFilePath.split('/').pop()
|
|
|
|
|
fileName = (fallbackName && fallbackName.length > 0) ? fallbackName : qsTr("backup.tgz")
|
|
|
|
|
}
|
|
|
|
|
fileName = String(fileName)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Extract IP address from filename
|
2026-02-04 23:03:38 +03:00
|
|
|
var serverIp = ""
|
|
|
|
|
var ipMatch = fileName.match(/^([\d_]+)\s*-/)
|
|
|
|
|
if (ipMatch && ipMatch.length > 1) {
|
|
|
|
|
serverIp = ipMatch[1].replace(/_/g, ".")
|
|
|
|
|
}
|
|
|
|
|
if (!serverIp || serverIp.length === 0) {
|
|
|
|
|
serverIp = root.restoreHostname
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var serverName = root.restoreHostname
|
|
|
|
|
if (!serverName || serverName.length === 0) {
|
|
|
|
|
serverName = qsTr("RestoredServer")
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Navigate to installation page
|
2026-02-04 23:03:38 +03:00
|
|
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Immediately find StackView and navigate to restore page
|
|
|
|
|
// Server already added, as we waited for onInstallServerFinished
|
2026-02-04 23:03:38 +03:00
|
|
|
Qt.callLater(function() {
|
|
|
|
|
var pagePath = "qrc:/ui/qml/Pages2/PageSettingsServerRestoreMode.qml"
|
2026-05-29 15:51:22 +03:00
|
|
|
|
|
|
|
|
// Traverse upward from root to find the containing StackView.
|
|
|
|
|
// StackView has both `push` function and `depth` property.
|
|
|
|
|
// This avoids a recursive downward search that causes stack overflow
|
|
|
|
|
// on iOS when the component tree is large (many VPN managers).
|
|
|
|
|
var stackView = root.parent
|
|
|
|
|
while (stackView) {
|
|
|
|
|
if (typeof stackView.push === "function" && stackView.hasOwnProperty("depth")) {
|
|
|
|
|
break
|
2026-02-04 23:03:38 +03:00
|
|
|
}
|
2026-05-29 15:51:22 +03:00
|
|
|
stackView = stackView.parent
|
2026-02-04 23:03:38 +03:00
|
|
|
}
|
2026-05-29 15:51:22 +03:00
|
|
|
|
2026-02-04 23:03:38 +03:00
|
|
|
if (stackView) {
|
|
|
|
|
console.log("Found StackView, pushing restore mode page")
|
|
|
|
|
stackView.push(pagePath, {
|
|
|
|
|
"backupFilePath": root.backupFilePath,
|
|
|
|
|
"backupFileName": fileName,
|
2026-05-29 15:51:22 +03:00
|
|
|
"serverName": "",
|
2026-02-04 23:03:38 +03:00
|
|
|
"serverIp": serverIp,
|
|
|
|
|
"isFromSetupWizard": true,
|
|
|
|
|
"wizardHostname": root.restoreHostname,
|
|
|
|
|
"wizardUsername": root.restoreUsername,
|
|
|
|
|
"wizardSecretData": root.restoreSecretData
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
console.error("Could not find StackView")
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-31 20:38:13 +09:00
|
|
|
|
2023-05-22 00:10:51 +08:00
|
|
|
SortFilterProxyModel {
|
|
|
|
|
id: proxyContainersModel
|
2025-08-06 04:35:51 +02:00
|
|
|
|
2023-05-22 00:10:51 +08:00
|
|
|
sourceModel: ContainersModel
|
|
|
|
|
filters: [
|
|
|
|
|
ValueFilter {
|
|
|
|
|
roleName: "isEasySetupContainer"
|
|
|
|
|
value: true
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
sorters: RoleSorter {
|
2023-09-18 21:06:10 +05:00
|
|
|
roleName: "easySetupOrder"
|
2023-05-22 00:10:51 +08:00
|
|
|
sortOrder: Qt.DescendingOrder
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-05 15:49:10 +08:00
|
|
|
BackButtonType {
|
|
|
|
|
id: backButton
|
|
|
|
|
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: parent.right
|
2026-04-30 14:53:03 +08:00
|
|
|
anchors.topMargin: 20 + PageController.safeAreaTopMargin
|
2025-08-06 04:35:51 +02:00
|
|
|
|
|
|
|
|
onActiveFocusChanged: {
|
|
|
|
|
if(backButton.enabled && backButton.activeFocus) {
|
|
|
|
|
listView.positionViewAtBeginning()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ButtonGroup {
|
|
|
|
|
id: buttonGroup
|
2023-06-05 15:49:10 +08:00
|
|
|
}
|
|
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
ListViewType {
|
|
|
|
|
id: listView
|
|
|
|
|
|
|
|
|
|
property int dockerContainer
|
|
|
|
|
property int containerDefaultPort
|
|
|
|
|
property int containerDefaultTransportProto
|
|
|
|
|
|
2023-06-05 15:49:10 +08:00
|
|
|
anchors.top: backButton.bottom
|
2023-06-20 10:25:24 +09:00
|
|
|
anchors.bottom: parent.bottom
|
2025-08-06 04:35:51 +02:00
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.right: parent.right
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
spacing: 16
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
header: ColumnLayout {
|
|
|
|
|
width: listView.width
|
2023-04-14 19:31:10 +03:00
|
|
|
|
|
|
|
|
spacing: 16
|
|
|
|
|
|
2025-05-02 23:54:36 -07:00
|
|
|
BaseHeaderType {
|
2023-05-25 15:40:17 +08:00
|
|
|
id: header
|
|
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.rightMargin: 16
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.bottomMargin: 16
|
|
|
|
|
|
2023-10-02 16:31:50 +05:00
|
|
|
headerTextMaximumLineCount: 10
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-02-04 15:53:40 +00:00
|
|
|
headerText: qsTr("Choose Installation Type")
|
2023-04-14 19:31:10 +03:00
|
|
|
}
|
2025-08-06 04:35:51 +02:00
|
|
|
}
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
model: proxyContainersModel
|
|
|
|
|
currentIndex: 0
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
delegate: ColumnLayout {
|
|
|
|
|
width: listView.width
|
2023-04-14 19:31:10 +03:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
CardType {
|
|
|
|
|
id: card
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.rightMargin: 16
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.bottomMargin: 16
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
headerText: easySetupHeader
|
|
|
|
|
bodyText: easySetupDescription
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
ButtonGroup.group: buttonGroup
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
onClicked: function() {
|
|
|
|
|
isEasySetup = true
|
2026-01-30 06:42:29 +02:00
|
|
|
checked = true
|
2025-08-06 04:35:51 +02:00
|
|
|
var defaultContainerProto = ContainerProps.defaultProtocol(dockerContainer)
|
2025-08-01 05:56:02 +02:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
listView.dockerContainer = dockerContainer
|
2026-04-30 14:53:03 +08:00
|
|
|
listView.containerDefaultPort = InstallController.getPortForInstall(defaultContainerProto)
|
|
|
|
|
listView.containerDefaultTransportProto = InstallController.defaultTransportProto(defaultContainerProto)
|
2024-01-20 23:28:20 +07:00
|
|
|
}
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
Keys.onReturnPressed: this.clicked()
|
|
|
|
|
Keys.onEnterPressed: this.clicked()
|
2023-07-31 20:38:13 +09:00
|
|
|
}
|
2025-08-06 04:35:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
footer: ColumnLayout {
|
|
|
|
|
width: listView.width
|
|
|
|
|
spacing: 16
|
2023-07-31 20:38:13 +09:00
|
|
|
|
2023-08-28 14:18:41 +03:00
|
|
|
DividerType {
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
2023-08-28 14:18:41 +03:00
|
|
|
}
|
2023-08-20 13:36:54 +05:00
|
|
|
|
2023-07-31 20:38:13 +09:00
|
|
|
CardType {
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
2023-07-31 20:38:13 +09:00
|
|
|
|
2025-02-04 15:53:40 +00:00
|
|
|
headerText: qsTr("Manual")
|
|
|
|
|
bodyText: qsTr("Choose a VPN protocol")
|
2023-07-31 20:38:13 +09:00
|
|
|
|
|
|
|
|
ButtonGroup.group: buttonGroup
|
2023-05-22 00:10:51 +08:00
|
|
|
|
2023-07-31 20:38:13 +09:00
|
|
|
onClicked: function() {
|
|
|
|
|
isEasySetup = false
|
2025-08-06 04:35:51 +02:00
|
|
|
checked = true
|
2023-05-22 00:10:51 +08:00
|
|
|
}
|
2025-08-01 05:56:02 +02:00
|
|
|
|
|
|
|
|
Keys.onEnterPressed: this.clicked()
|
|
|
|
|
Keys.onReturnPressed: this.clicked()
|
2023-04-14 19:31:10 +03:00
|
|
|
}
|
|
|
|
|
|
2026-02-04 23:03:38 +03:00
|
|
|
DividerType {
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CardType {
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
|
|
|
|
|
|
|
|
|
headerText: qsTr("Restore from backup")
|
|
|
|
|
bodyText: qsTr("Restoration of VPN protocols, services, all server settings and users")
|
|
|
|
|
|
|
|
|
|
ButtonGroup.group: buttonGroup
|
|
|
|
|
|
|
|
|
|
onClicked: function() {
|
|
|
|
|
|
|
|
|
|
var filter = GC.isMobile() ? "*.gz *.tgz *.tar.gz" : "Backup files (*.tar.gz *.backup *.tgz *.gz)"
|
|
|
|
|
var localPath = SystemController.getFileName(
|
|
|
|
|
qsTr("Select Backup to Restore"),
|
|
|
|
|
filter,
|
|
|
|
|
"",
|
|
|
|
|
false,
|
|
|
|
|
""
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
console.log("Selected file path:", localPath)
|
|
|
|
|
|
|
|
|
|
if (!localPath || localPath.length === 0) {
|
|
|
|
|
console.log("No file selected")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Save backup file path
|
2026-02-04 23:03:38 +03:00
|
|
|
root.backupFilePath = localPath
|
|
|
|
|
root.isRestoreFromBackup = true
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Get credentials from PageSetupWizardCredentials via StackView search
|
2026-02-04 23:03:38 +03:00
|
|
|
var credentialsPage = null
|
|
|
|
|
var item = root
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Find StackView
|
2026-02-04 23:03:38 +03:00
|
|
|
while (item && !item.hasOwnProperty("depth")) {
|
|
|
|
|
item = item.parent
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// If found StackView, search for PageSetupWizardCredentials in its history
|
2026-02-04 23:03:38 +03:00
|
|
|
if (item && item.depth > 0) {
|
|
|
|
|
for (var i = 0; i < item.depth; i++) {
|
|
|
|
|
var page = item.get(i)
|
|
|
|
|
if (page && page.hasOwnProperty("savedHostname")) {
|
|
|
|
|
credentialsPage = page
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (credentialsPage && credentialsPage.savedHostname.length > 0) {
|
|
|
|
|
root.restoreHostname = credentialsPage.savedHostname
|
|
|
|
|
root.restoreUsername = credentialsPage.savedUsername
|
|
|
|
|
root.restoreSecretData = credentialsPage.savedSecretData
|
|
|
|
|
console.log("Got credentials from PageSetupWizardCredentials:", root.restoreHostname, root.restoreUsername)
|
|
|
|
|
|
2026-02-06 17:14:08 +03:00
|
|
|
// Call C++ method to prepare restore
|
|
|
|
|
// It will scan backup and send readyForRestore signal
|
|
|
|
|
ServersBackupController.prepareRestoreFromBackup(localPath, root.restoreHostname, root.restoreUsername, root.restoreSecretData)
|
2026-02-04 23:03:38 +03:00
|
|
|
} else {
|
|
|
|
|
console.log("WARNING: No credentials found")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Keys.onEnterPressed: this.clicked()
|
|
|
|
|
Keys.onReturnPressed: this.clicked()
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 19:31:10 +03:00
|
|
|
BasicButtonType {
|
2023-06-05 15:49:10 +08:00
|
|
|
id: continueButton
|
2023-05-25 15:40:17 +08:00
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
2023-05-22 00:10:51 +08:00
|
|
|
|
|
|
|
|
text: qsTr("Continue")
|
|
|
|
|
|
2024-02-17 23:09:05 +02:00
|
|
|
clickedFunc: function() {
|
2023-07-31 20:38:13 +09:00
|
|
|
if (root.isEasySetup) {
|
2026-04-30 14:53:03 +08:00
|
|
|
ServersUiController.processedContainerIndex = listView.dockerContainer
|
2023-09-06 13:37:37 +05:00
|
|
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
2025-08-06 04:35:51 +02:00
|
|
|
InstallController.install(listView.dockerContainer,
|
2026-05-15 12:33:36 +08:00
|
|
|
listView.containerDefaultPort,
|
|
|
|
|
listView.containerDefaultTransportProto,
|
2026-05-28 10:57:08 +08:00
|
|
|
ServersUiController.processedServerId)
|
2023-07-31 20:38:13 +09:00
|
|
|
} else {
|
2023-09-06 13:37:37 +05:00
|
|
|
PageController.goToPage(PageEnum.PageSetupWizardProtocols)
|
2023-07-31 20:38:13 +09:00
|
|
|
}
|
2023-05-22 00:10:51 +08:00
|
|
|
}
|
2023-04-14 19:31:10 +03:00
|
|
|
}
|
2023-08-20 13:36:54 +05:00
|
|
|
|
|
|
|
|
BasicButtonType {
|
2023-08-28 14:18:41 +03:00
|
|
|
id: setupLaterButton
|
|
|
|
|
|
2025-08-06 04:35:51 +02:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
Layout.topMargin: 8
|
|
|
|
|
Layout.bottomMargin: 24
|
|
|
|
|
Layout.leftMargin: 16
|
|
|
|
|
Layout.rightMargin: 16
|
2023-08-20 13:36:54 +05:00
|
|
|
|
2024-07-07 13:42:38 +03:00
|
|
|
defaultColor: AmneziaStyle.color.transparent
|
2024-08-20 16:54:05 +07:00
|
|
|
hoveredColor: AmneziaStyle.color.translucentWhite
|
|
|
|
|
pressedColor: AmneziaStyle.color.sheerWhite
|
|
|
|
|
disabledColor: AmneziaStyle.color.mutedGray
|
|
|
|
|
textColor: AmneziaStyle.color.paleGray
|
2023-08-20 13:36:54 +05:00
|
|
|
borderWidth: 1
|
|
|
|
|
|
2023-10-01 12:11:13 +08:00
|
|
|
visible: {
|
2023-10-03 22:38:17 +05:00
|
|
|
if (PageController.isTriggeredByConnectButton()) {
|
2024-02-29 17:22:17 +07:00
|
|
|
PageController.setTriggeredByConnectButton(false)
|
|
|
|
|
return false
|
2023-10-01 12:11:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
2023-09-25 07:22:11 +08:00
|
|
|
|
2024-03-26 20:05:04 +02:00
|
|
|
text: qsTr("Skip setup")
|
2023-08-20 13:36:54 +05:00
|
|
|
|
2024-02-17 23:09:05 +02:00
|
|
|
clickedFunc: function() {
|
2023-09-06 13:37:37 +05:00
|
|
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
2023-08-20 13:36:54 +05:00
|
|
|
InstallController.addEmptyServer()
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-14 19:31:10 +03:00
|
|
|
}
|
2025-08-06 04:35:51 +02:00
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
|
|
|
|
var item = listView.itemAtIndex(listView.currentIndex)
|
|
|
|
|
if (item !== null) {
|
|
|
|
|
var button = item.children[0]
|
|
|
|
|
button.checked = true
|
|
|
|
|
button.clicked()
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-14 19:31:10 +03:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-06 04:35:51 +02:00
|
|
|
|