logos-blockchain-ui/src/qml/BlockchainView.qml

153 lines
6.8 KiB
QML
Raw Normal View History

2026-02-11 20:39:32 +01:00
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import BlockchainBackend
import Logos.Theme
2026-02-11 20:39:32 +01:00
2026-02-19 13:31:33 +01:00
import "views"
2026-02-11 20:39:32 +01:00
Rectangle {
id: root
QtObject {
id: _d
function getStatusString(status) {
switch(status) {
case BlockchainBackend.NotStarted: return qsTr("Not Started");
case BlockchainBackend.Starting: return qsTr("Starting...");
case BlockchainBackend.Running: return qsTr("Running");
case BlockchainBackend.Stopping: return qsTr("Stopping...");
case BlockchainBackend.Stopped: return qsTr("Stopped");
case BlockchainBackend.Error: return qsTr("Error");
case BlockchainBackend.ErrorNotInitialized: return qsTr("Error: Module not initialized");
case BlockchainBackend.ErrorConfigMissing: return qsTr("Error: Config path missing");
case BlockchainBackend.ErrorStartFailed: return qsTr("Error: Failed to start node");
case BlockchainBackend.ErrorStopFailed: return qsTr("Error: Failed to stop node");
case BlockchainBackend.ErrorSubscribeFailed: return qsTr("Error: Failed to subscribe to events");
default: return qsTr("Unknown");
}
}
function getStatusColor(status) {
switch(status) {
case BlockchainBackend.Running: return Theme.palette.success;
case BlockchainBackend.Starting: return Theme.palette.warning;
case BlockchainBackend.Stopping: return Theme.palette.warning;
case BlockchainBackend.NotStarted: return Theme.palette.error;
case BlockchainBackend.Stopped: return Theme.palette.error;
case BlockchainBackend.Error:
case BlockchainBackend.ErrorNotInitialized:
case BlockchainBackend.ErrorConfigMissing:
case BlockchainBackend.ErrorStartFailed:
case BlockchainBackend.ErrorStopFailed:
case BlockchainBackend.ErrorSubscribeFailed: return Theme.palette.error;
default: return Theme.palette.textSecondary;
}
}
2026-02-24 17:05:46 +01:00
property int currentPage: 0 // 0 = config choice (page 1), 1 = node + wallet + logs (page 2)
2026-02-11 20:39:32 +01:00
}
color: Theme.palette.background
2026-02-24 17:05:46 +01:00
StackLayout {
2026-02-11 20:39:32 +01:00
anchors.fill: parent
anchors.margins: Theme.spacing.large
2026-02-24 17:05:46 +01:00
currentIndex: _d.currentPage
// Page 1: Config choice (Option 1: Generate own config, Option 2: Set path to configs)
ScrollView {
id: configChoiceScrollView
clip: true
ConfigChoiceView {
id: configChoiceView
width: configChoiceScrollView.availableWidth
userConfigPath: backend.userConfig
deploymentConfigPath: backend.deploymentConfig
generatedUserConfigPath: backend.generatedUserConfigPath
onUserConfigPathSelected: function(path) { backend.userConfig = path }
onDeploymentConfigPathSelected: function(path) { backend.deploymentConfig = path }
onSetPathToConfigsRequested: function() {
backend.useGeneratedConfig = false
_d.currentPage = 1
}
onGenerateRequested: function(outputPath, initialPeers, netPort, blendPort, httpAddr, externalAddress, noPublicIpCheck, deploymentMode, deploymentConfigPath, statePath) {
configChoiceView.generateResultSuccess = false
configChoiceView.generateResultMessage = ""
var code = backend.generateConfig(outputPath, initialPeers, netPort, blendPort, httpAddr, externalAddress, noPublicIpCheck, deploymentMode, deploymentConfigPath, statePath)
configChoiceView.generateResultSuccess = (code === 0)
configChoiceView.generateResultMessage = code === 0 ? qsTr("Config generated successfully.") : qsTr("Generate failed (code: %1).").arg(code)
if (code === 0) {
backend.userConfig = (outputPath !== "") ? outputPath : backend.generatedUserConfigPath
backend.deploymentConfig = (deploymentMode === 1 && deploymentConfigPath !== "") ? deploymentConfigPath : ""
backend.useGeneratedConfig = true
_d.currentPage = 1
}
}
2026-02-11 20:39:32 +01:00
}
2026-02-24 17:05:46 +01:00
}
2026-02-11 20:39:32 +01:00
2026-02-24 17:05:46 +01:00
// Page 2: Start node, balances, transfer, logs
SplitView {
orientation: Qt.Vertical
2026-02-11 20:39:32 +01:00
2026-02-26 17:21:25 +01:00
ColumnLayout {
2026-02-24 17:05:46 +01:00
SplitView.fillWidth: true
SplitView.minimumHeight: 200
2026-02-26 17:21:25 +01:00
spacing: Theme.spacing.large
2026-02-24 17:05:46 +01:00
StatusConfigView {
2026-02-26 17:21:25 +01:00
Layout.fillWidth: true
2026-02-24 17:05:46 +01:00
statusText: _d.getStatusString(backend.status)
statusColor: _d.getStatusColor(backend.status)
userConfig: backend.userConfig
deploymentConfig: backend.deploymentConfig
useGeneratedConfig: backend.useGeneratedConfig
canStart: !!backend.userConfig
&& backend.status !== BlockchainBackend.Starting
&& backend.status !== BlockchainBackend.Stopping
isRunning: backend.status === BlockchainBackend.Running
onStartRequested: backend.startBlockchain()
onStopRequested: backend.stopBlockchain()
onChangeConfigRequested: _d.currentPage = 0
2026-02-11 20:39:32 +01:00
}
2026-02-24 17:05:46 +01:00
WalletView {
id: walletView
2026-02-26 17:21:25 +01:00
accountsModel: backend.accountsModel
2026-02-24 17:05:46 +01:00
onGetBalanceRequested: function(addressHex) {
2026-02-26 17:21:25 +01:00
var result = backend.getBalance(addressHex)
if ((result || "").indexOf("Error") === 0) {
lastBalanceErrorAddress = addressHex
lastBalanceError = result
}
else {
lastBalanceErrorAddress = ""
lastBalanceError = ""
}
2026-02-24 17:05:46 +01:00
}
2026-02-26 17:21:25 +01:00
onCopyToClipboard: (text) => backend.copyToClipboard(text)
2026-02-24 17:05:46 +01:00
onTransferRequested: function(fromKeyHex, toKeyHex, amount) {
walletView.setTransferResult(backend.transferFunds(fromKeyHex, toKeyHex, amount))
}
2026-02-11 20:39:32 +01:00
}
2026-02-26 17:21:25 +01:00
Item {
Layout.preferredHeight: Theme.spacing.small
}
2026-02-11 20:39:32 +01:00
}
2026-02-24 17:05:46 +01:00
LogsView {
SplitView.fillWidth: true
SplitView.minimumHeight: 150
2026-02-11 20:39:32 +01:00
2026-02-24 17:05:46 +01:00
logModel: backend.logModel
onClearRequested: backend.clearLogs()
onCopyToClipboard: (text) => backend.copyToClipboard(text)
}
2026-02-11 20:39:32 +01:00
}
}
}