mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-06-14 12:29:26 +00:00
commit
4691d8b5df
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ libs
|
||||
app/build
|
||||
CMakeLists.txt.user
|
||||
generated_code
|
||||
.cache
|
||||
@ -213,7 +213,7 @@ if(_storage_module_is_source)
|
||||
|
||||
# Add custom target to run the cpp generator for the storage module
|
||||
add_custom_target(run_cpp_generator_storage_module
|
||||
COMMAND "${CPP_GENERATOR}" "${PLUGIN_FILE}" --module-only --output-dir "${PLUGINS_OUTPUT_DIR}"
|
||||
COMMAND "${CPP_GENERATOR}" "${PLUGIN_FILE}" --interface "${LOGOS_STORAGE_ROOT}/storage_module_interface.h" --module-only --output-dir "${PLUGINS_OUTPUT_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Running logos-cpp-generator on ${PLUGIN_FILE} with output-dir ${PLUGINS_OUTPUT_DIR}"
|
||||
VERBATIM
|
||||
@ -349,6 +349,8 @@ endif()
|
||||
|
||||
if(_cpp_sdk_is_source)
|
||||
target_include_directories(storage_ui PRIVATE
|
||||
|
||||
#${PLUGINS_OUTPUT_DIR}
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp/generated
|
||||
)
|
||||
|
||||
175
flake.lock
generated
175
flake.lock
generated
@ -1,32 +1,38 @@
|
||||
{
|
||||
"nodes": {
|
||||
"circom-compat": {
|
||||
"logos-capability-module": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": [
|
||||
"logos-cpp-sdk"
|
||||
],
|
||||
"logos-liblogos": "logos-liblogos",
|
||||
"nixpkgs": [
|
||||
"logos-storage-module",
|
||||
"logos-storage",
|
||||
"logos-capability-module",
|
||||
"logos-liblogos",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1736521871,
|
||||
"narHash": "sha256-d34XNLg9NGPEOARHW+BIOAWalkHdEUAwsv3mpLZQxds=",
|
||||
"owner": "logos-storage",
|
||||
"repo": "circom-compat-ffi",
|
||||
"rev": "8cd4ed44fdafe59d4ec1184420639cae4c4dbab9",
|
||||
"lastModified": 1767809111,
|
||||
"narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-capability-module",
|
||||
"rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "logos-storage",
|
||||
"repo": "circom-compat-ffi",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-capability-module",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-capability-module": {
|
||||
"logos-capability-module_2": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk",
|
||||
"logos-liblogos": "logos-liblogos",
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_3",
|
||||
"logos-liblogos": "logos-liblogos_4",
|
||||
"nixpkgs": [
|
||||
"logos-storage-module",
|
||||
"logos-liblogos",
|
||||
"logos-capability-module",
|
||||
"logos-liblogos",
|
||||
"nixpkgs"
|
||||
@ -68,6 +74,25 @@
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770978598,
|
||||
"narHash": "sha256-CR5N5v+y2ZInnBocGgjIeLaS9XqNjAKGXE2abC3E110=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"rev": "c3477d29e32cae5f73ca637fb81e547f8a6cba58",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "logos-co",
|
||||
"ref": "feat/logos-result",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-cpp-sdk_3": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1761230734,
|
||||
"narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=",
|
||||
@ -82,34 +107,16 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-cpp-sdk_3": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767724329,
|
||||
"narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-cpp-sdk_4": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1764699992,
|
||||
"narHash": "sha256-nCmK9C9F31cHvy6lWKR5WGl99aJbS3kIsROAoZ4OrwI=",
|
||||
"lastModified": 1761230734,
|
||||
"narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"rev": "5d0bbd0d1e00aad0532ffa7c8bf2c80f460a4f6d",
|
||||
"rev": "4b143922c190df00bb3835441c9f0075cb28283b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -141,11 +148,11 @@
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1764699992,
|
||||
"narHash": "sha256-nCmK9C9F31cHvy6lWKR5WGl99aJbS3kIsROAoZ4OrwI=",
|
||||
"lastModified": 1767724329,
|
||||
"narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-cpp-sdk",
|
||||
"rev": "5d0bbd0d1e00aad0532ffa7c8bf2c80f460a4f6d",
|
||||
"rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -156,7 +163,7 @@
|
||||
},
|
||||
"logos-liblogos": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_2",
|
||||
"logos-cpp-sdk": "logos-cpp-sdk",
|
||||
"nixpkgs": [
|
||||
"logos-capability-module",
|
||||
"logos-liblogos",
|
||||
@ -180,7 +187,9 @@
|
||||
},
|
||||
"logos-liblogos_2": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_4",
|
||||
"logos-cpp-sdk": [
|
||||
"logos-cpp-sdk"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"logos-liblogos",
|
||||
"logos-cpp-sdk",
|
||||
@ -204,7 +213,9 @@
|
||||
},
|
||||
"logos-liblogos_3": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_6",
|
||||
"logos-capability-module": "logos-capability-module_2",
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_5",
|
||||
"logos-module": "logos-module",
|
||||
"nixpkgs": [
|
||||
"logos-storage-module",
|
||||
"logos-liblogos",
|
||||
@ -213,11 +224,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767722338,
|
||||
"narHash": "sha256-89RYfnramvJRufy47Kdx662TMHaFVSpS88ouWff3Csw=",
|
||||
"lastModified": 1770837874,
|
||||
"narHash": "sha256-wr75lv1q4U1FS5+l/6ypwzJFJe06l2RyUvx1npoRS88=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-liblogos",
|
||||
"rev": "ca1fda7cabd70027e51d86392f5e29b3fff385f9",
|
||||
"rev": "e3741c01fd3abf6b7bd9ff2fa8edf89c41fc0cea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -226,17 +237,67 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-liblogos_4": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_4",
|
||||
"nixpkgs": [
|
||||
"logos-storage-module",
|
||||
"logos-liblogos",
|
||||
"logos-capability-module",
|
||||
"logos-liblogos",
|
||||
"logos-cpp-sdk",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1761845775,
|
||||
"narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-liblogos",
|
||||
"rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-liblogos",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-module": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_6",
|
||||
"nixpkgs": [
|
||||
"logos-storage-module",
|
||||
"logos-liblogos",
|
||||
"logos-module",
|
||||
"logos-cpp-sdk",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770062426,
|
||||
"narHash": "sha256-zc7ZxDTlqOCYGyEHhrTA/7GS1EWh7+4amdPUKh+gGds=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-module",
|
||||
"rev": "f7ee69d9ad9f27c84f04f59896e9194125e951dc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-module",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"logos-storage": {
|
||||
"inputs": {
|
||||
"circom-compat": "circom-compat",
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769016529,
|
||||
"narHash": "sha256-pzUrdFKSEraZQzO2a9Uj5oDMas+Vtpu6+p4bG+lRnsk=",
|
||||
"lastModified": 1770982130,
|
||||
"narHash": "sha256-qsTf54BP2yEJEDHVR1lgtZ1u2wm7TK5MUHgwUiX6wU0=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "3c09f008bb5266a669fd19f18368f9e8b861b664",
|
||||
"revCount": 877,
|
||||
"rev": "e375223500ca0fd919b0e504eab65c6ddb5e4233",
|
||||
"revCount": 897,
|
||||
"submodules": true,
|
||||
"type": "git",
|
||||
"url": "https://github.com/logos-storage/logos-storage-nim"
|
||||
@ -249,7 +310,9 @@
|
||||
},
|
||||
"logos-storage-module": {
|
||||
"inputs": {
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_5",
|
||||
"logos-cpp-sdk": [
|
||||
"logos-cpp-sdk"
|
||||
],
|
||||
"logos-liblogos": "logos-liblogos_3",
|
||||
"logos-storage": "logos-storage",
|
||||
"nixpkgs": [
|
||||
@ -259,11 +322,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769611047,
|
||||
"narHash": "sha256-U8lV4hgntPTMO0wpyIDFKMN1N3jSGnxKDCGHS9WoEb8=",
|
||||
"lastModified": 1771221082,
|
||||
"narHash": "sha256-dpygXvcVOExNXHkUH+/XcR/xBVFKNjw/i9aChSXcZNk=",
|
||||
"owner": "logos-co",
|
||||
"repo": "logos-storage-module",
|
||||
"rev": "14cc30674980685442e66639c37c587263520147",
|
||||
"rev": "b4ecf7a871233608f63b817eeae426f6273695d9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -370,11 +433,11 @@
|
||||
},
|
||||
"nixpkgs_7": {
|
||||
"locked": {
|
||||
"lastModified": 1736200483,
|
||||
"narHash": "sha256-JO+lFN2HsCwSLMUWXHeOad6QUxOuwe9UOAF/iSl1J4I=",
|
||||
"lastModified": 1751274312,
|
||||
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "3f0a8ac25fb674611b98089ca3a5dd6480175751",
|
||||
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -387,7 +450,7 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"logos-capability-module": "logos-capability-module",
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_3",
|
||||
"logos-cpp-sdk": "logos-cpp-sdk_2",
|
||||
"logos-liblogos": "logos-liblogos_2",
|
||||
"logos-storage-module": "logos-storage-module",
|
||||
"nixpkgs": [
|
||||
|
||||
@ -4,10 +4,16 @@
|
||||
inputs = {
|
||||
# Follow the same nixpkgs as logos-liblogos to ensure compatibility
|
||||
nixpkgs.follows = "logos-liblogos/nixpkgs";
|
||||
logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk";
|
||||
# logos-cpp-sdk.url = "/home/arnaud/Work/logos/logos-cpp-sdk";
|
||||
logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk?ref=feat/logos-result";
|
||||
logos-liblogos.url = "github:logos-co/logos-liblogos?ref=fix/logos-cleanup-on-terminate";
|
||||
logos-storage-module.url = "github:logos-co/logos-storage-module";
|
||||
#logos-storage-module.url = "path:/home/arnaud/Work/logos/logos-storage-module";
|
||||
logos-capability-module.url = "github:logos-co/logos-capability-module";
|
||||
|
||||
logos-liblogos.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk";
|
||||
logos-storage-module.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk";
|
||||
logos-capability-module.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, logos-cpp-sdk, logos-liblogos, logos-storage-module, logos-capability-module }:
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
#include "StorageBackend.h"
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLocale>
|
||||
|
||||
// StorageBackend is responsible for managing the interaction with the storage module.
|
||||
// It is mocked in the QML.
|
||||
// There are currently 2 ways to display debug information:
|
||||
// - the first one is to log only in the console using qDebug/qWarning. This is basically
|
||||
// for developers: entering a function, sending a command to the storage module...
|
||||
// - the second one is to use the "debug" helper that logs both in the console and in a
|
||||
// QString property that can be displayed in the UI. This is more for users to understand
|
||||
// what is happening.
|
||||
StorageBackend::StorageBackend(LogosAPI* logosAPI, QObject* parent)
|
||||
: QObject(parent), m_status(Destroyed), m_logosAPI(nullptr), m_logos(nullptr) {
|
||||
qDebug() << "Initializing StorageBackend...";
|
||||
@ -17,8 +27,6 @@ StorageBackend::StorageBackend(LogosAPI* logosAPI, QObject* parent)
|
||||
}
|
||||
|
||||
m_logos = new LogosModules(m_logosAPI);
|
||||
|
||||
initStorage();
|
||||
}
|
||||
|
||||
StorageBackend::~StorageBackend()
|
||||
@ -27,97 +35,223 @@ StorageBackend::~StorageBackend()
|
||||
m_logos = nullptr;
|
||||
}
|
||||
|
||||
void StorageBackend::initStorage() {
|
||||
LogosResult StorageBackend::init(const QString& configJson = "{}") {
|
||||
qDebug() << "StorageBackend::initStorage called";
|
||||
|
||||
bool result = m_logos->storage_module.init("{}");
|
||||
bool result = m_logos->storage_module.init(m_configJson);
|
||||
|
||||
qDebug() << "StorageBackend::initStorage: init result =" << result;
|
||||
qDebug() << "StorageBackend::initStorage: init";
|
||||
|
||||
if (!result) {
|
||||
qDebug() << "StorageBackend: Failed to initialise Storage module.";
|
||||
setStatus(Destroyed, "Failed to initialise Storage module.");
|
||||
return;
|
||||
setStatus(Destroyed);
|
||||
debug("Failed to init storage");
|
||||
return {false, "", "Filed to init storage"};
|
||||
}
|
||||
|
||||
setStatus(Stopped, "Storage module ready.");
|
||||
setStatus(Stopped);
|
||||
|
||||
if (!m_logos->storage_module.on("storageStart", [this](const QVariantList& data) {
|
||||
int code = data[0].toInt();
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (code != RET_OK) {
|
||||
qDebug() << "StorageBackend: storageStart event failure with code" << code;
|
||||
setStatus(Stopped, "Failed to start Storage module.");
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
setStatus(Stopped);
|
||||
debug("Failed to start Storage module:" + message);
|
||||
} else {
|
||||
qDebug() << "StorageBackend: storageStart event success";
|
||||
setStatus(Running, "Storage module started.");
|
||||
setStatus(Running);
|
||||
debug("Storage module started.");
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageStart events";
|
||||
}
|
||||
|
||||
if (!m_logos->storage_module.on("storageStop", [this](const QVariantList& data) {
|
||||
int code = data[0].toInt();
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (code != RET_OK) {
|
||||
qDebug() << "StorageBackend: storageStop event failure with code" << code;
|
||||
setStatus(Running, "Failed to stop Storage module.");
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
setStatus(Running);
|
||||
debug("Failed to stop Storage module:" + message);
|
||||
} else {
|
||||
qDebug() << "StorageBackend: storageStop event success";
|
||||
setStatus(Stopped, "Storage module stopped.");
|
||||
setStatus(Stopped);
|
||||
debug("Storage module stopped.");
|
||||
emit stopped();
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageStop events";
|
||||
}
|
||||
|
||||
startStop();
|
||||
if (!m_logos->storage_module.on("storageConnect", [this](const QVariantList& data) {
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
debug("Failed to connect: " + message);
|
||||
} else {
|
||||
// TODO add the peer id
|
||||
debug("Successfully connected to peer.");
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageConnect events";
|
||||
}
|
||||
|
||||
if (!m_logos->storage_module.on("storageUploadProgress", [this](const QVariantList& data) {
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
debug("Failure during upload progress: " + message);
|
||||
m_uploadStatus = "Error: " + message;
|
||||
emit uploadStatusChanged();
|
||||
} else {
|
||||
QString sessionId = data[1].toString();
|
||||
qint64 len = data[2].toLongLong();
|
||||
|
||||
m_uploadedBytes += len;
|
||||
|
||||
// Calcule le pourcentage
|
||||
if (m_uploadTotalBytes > 0) {
|
||||
m_uploadProgress = (m_uploadedBytes * 100) / m_uploadTotalBytes;
|
||||
}
|
||||
|
||||
m_uploadStatus = QString("Uploading: %1 / %2 bytes (%3%)")
|
||||
.arg(m_uploadedBytes)
|
||||
.arg(m_uploadTotalBytes)
|
||||
.arg(m_uploadProgress);
|
||||
|
||||
emit uploadProgressChanged();
|
||||
emit uploadStatusChanged();
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events";
|
||||
}
|
||||
|
||||
if (!m_logos->storage_module.on("storageUploadDone", [this](const QVariantList& data) {
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
debug("Failed to upload: " + message);
|
||||
m_uploadProgress = 0;
|
||||
m_uploadStatus = "Upload failed";
|
||||
emit uploadProgressChanged();
|
||||
emit uploadStatusChanged();
|
||||
} else {
|
||||
QString sessionId = data[1].toString();
|
||||
m_cid = data[2].toString();
|
||||
emit cidChanged();
|
||||
debug("Upload completed for session " + sessionId + " with CID " + m_cid);
|
||||
|
||||
// Complète la progress bar
|
||||
m_uploadProgress = 100;
|
||||
m_uploadStatus = "Upload completed!";
|
||||
emit uploadProgressChanged();
|
||||
emit uploadStatusChanged();
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events";
|
||||
}
|
||||
|
||||
if (!m_logos->storage_module.on("storageDownloadProgress", [this](const QVariantList& data) {
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
debug("Failure during download progress: " + message);
|
||||
} else {
|
||||
QString sessionId = data[1].toString();
|
||||
int len = data[2].toInt();
|
||||
debug("Downloaded " + QString::number(len) + " bytes for session " + sessionId);
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageDownloadProgress events";
|
||||
}
|
||||
|
||||
if (!m_logos->storage_module.on("storageDownloadDone", [this](const QVariantList& data) {
|
||||
bool success = data[0].toBool();
|
||||
|
||||
if (!success) {
|
||||
QString message = data[1].toString();
|
||||
debug("Failed to download: " + message);
|
||||
} else {
|
||||
QString sessionId = data[1].toString();
|
||||
m_cid = data[2].toString();
|
||||
emit cidChanged();
|
||||
debug("Download completed for session " + sessionId + " with CID " + m_cid);
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageDownloadProgress events";
|
||||
}
|
||||
|
||||
m_configJson = configJson;
|
||||
emit configJsonChanged();
|
||||
|
||||
debug("config.json content is: " + m_configJson);
|
||||
|
||||
return {true, ""};
|
||||
}
|
||||
|
||||
void StorageBackend::setStatus(StorageStatus newStatus, QString statusText) {
|
||||
if (m_status != newStatus || m_statusText != statusText) {
|
||||
void StorageBackend::setStatus(StorageStatus newStatus) {
|
||||
if (m_status != newStatus) {
|
||||
m_status = newStatus;
|
||||
m_statusText = statusText;
|
||||
emit statusChanged();
|
||||
qDebug() << "StorageBackend: Status changed to" << m_status;
|
||||
}
|
||||
}
|
||||
|
||||
void StorageBackend::startStop() {
|
||||
qDebug() << "StorageBackend: startStop method called";
|
||||
LogosResult StorageBackend::start(const QString& newConfigJson) {
|
||||
qDebug() << "StorageBackend: start method called";
|
||||
|
||||
if (m_status == Destroyed || m_status == Starting || m_status == Stopping) {
|
||||
qDebug() << "StorageBackend: Cannot start/stop Storage in current state:" << m_status;
|
||||
return;
|
||||
if (newConfigJson != "") {
|
||||
reloadIfChanged(newConfigJson);
|
||||
}
|
||||
|
||||
if (m_status != Running) {
|
||||
qDebug() << "StorageBackend: Starting Storage...";
|
||||
setStatus(Starting, "Starting Storage module...");
|
||||
|
||||
bool result = m_logos->storage_module.start();
|
||||
|
||||
if (!result) {
|
||||
qDebug() << "StorageBackend: Failed to start Storage.";
|
||||
setStatus(Stopped, "Failed to start Storage module.");
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "StorageBackend: start command sent, waiting for events.";
|
||||
} else {
|
||||
stop();
|
||||
if (m_status != Stopped) {
|
||||
debug("The Storage Module is not initialised properly.");
|
||||
return {false, "", "The Storage Module is not initialised properly."};
|
||||
}
|
||||
|
||||
if (m_status == Running) {
|
||||
debug("The Storage Module is already started.");
|
||||
return {false, "", "The Storage Module is already started."};
|
||||
}
|
||||
|
||||
setStatus(Starting);
|
||||
debug("Starting Storage module...");
|
||||
|
||||
auto result = m_logos->storage_module.start();
|
||||
|
||||
if (!result) {
|
||||
setStatus(Stopped);
|
||||
debug("Failed to start storage");
|
||||
return {false, "", "Failed to start storage"};
|
||||
}
|
||||
|
||||
qDebug() << "StorageBackend: start command sent, waiting for events.";
|
||||
|
||||
return {true, ""};
|
||||
}
|
||||
|
||||
void StorageBackend::stop() {
|
||||
qDebug() << "StorageBackend: Stopping Storage...";
|
||||
setStatus(Stopping, "Stopping Storage module...");
|
||||
qDebug() << "StorageBackend: stop method called";
|
||||
|
||||
bool result = m_logos->storage_module.stop();
|
||||
if (m_status == StorageStatus::Stopping) {
|
||||
debug("The Storage Module is already stopping.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
qDebug() << "StorageBackend: Failed to stop Storage.";
|
||||
setStatus(Running, "Failed to stop Storage module.");
|
||||
if (m_status != StorageStatus::Running) {
|
||||
debug("The Storage Module is not started.");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(Stopping);
|
||||
debug("Stopping Storage module...");
|
||||
|
||||
auto result = m_logos->storage_module.stop();
|
||||
|
||||
if (!result.success) {
|
||||
setStatus(Running);
|
||||
debug(result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -128,29 +262,495 @@ void StorageBackend::destroy() {
|
||||
qDebug() << "StorageBackend: destroy method called";
|
||||
|
||||
StorageStatus status = m_status;
|
||||
int result = m_logos->storage_module.destroy();
|
||||
auto result = m_logos->storage_module.destroy();
|
||||
|
||||
if (!result) {
|
||||
qDebug() << "StorageBackend: Failed to destroy Storage module." << result;
|
||||
setStatus(status, "Failed to destroy Storage module.");
|
||||
if (!result.success) {
|
||||
debug(result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "StorageBackend: Storage module destroyed.";
|
||||
}
|
||||
|
||||
QString StorageBackend::statusText() const { return m_statusText; }
|
||||
QString StorageBackend::debugLogs() const { return m_debugLogs; };
|
||||
|
||||
QString StorageBackend::startStopText() const {
|
||||
if (m_status != Running) {
|
||||
return "Start";
|
||||
} else {
|
||||
return "Stop";
|
||||
void StorageBackend::debug(const QString& log) {
|
||||
if (!m_debugLogs.isEmpty()) {
|
||||
m_debugLogs += "\n";
|
||||
}
|
||||
|
||||
QString timestamp = QDateTime::currentDateTime().toString(Qt::ISODate);
|
||||
m_debugLogs += timestamp + ": " + log;
|
||||
emit debugLogsChanged();
|
||||
|
||||
qDebug() << "StorageBackend: " << log;
|
||||
}
|
||||
|
||||
bool StorageBackend::canStartStop() const { return m_status == Running || m_status == Stopped; }
|
||||
void StorageBackend::tryDebug() {
|
||||
auto result = m_logos->storage_module.debug();
|
||||
|
||||
bool StorageBackend::isRunning() { return m_status == Running; }
|
||||
debug("Debug " + result.getString());
|
||||
}
|
||||
void StorageBackend::tryPeerConnect(const QString& peerId) {
|
||||
qDebug().noquote() << "StorageBackend: tryPeerConnect called with peerId=" << peerId;
|
||||
|
||||
bool StorageBackend::isInitialised() { return m_status != Destroyed; }
|
||||
// LogosResult result2 = m_logos->storage_module.space();
|
||||
// QVariantMap space = result2.getValue<QVariantMap>();
|
||||
// int quotaMaxBytes = space["quotaMaxBytes"].toInt();
|
||||
// int quotaUsedBytes = space["quotaUsedBytes"].toInt();
|
||||
// int quotaReservedBytes = space["quotaReservedBytes"].toInt();
|
||||
|
||||
// int totalBlocks = result2.getValue<int>("totalBlocks");
|
||||
|
||||
// debug("totalBlocks " + QString::number(totalBlocks));
|
||||
// debug("quotaMaxBytes " + QString::number(quotaMaxBytes));
|
||||
// debug("quotaUsedBytes " + QString::number(quotaUsedBytes));
|
||||
// debug("quotaReservedBytes " + QString::number(quotaReservedBytes));
|
||||
|
||||
// LogosResult result = m_logos->storage_module.dataDir();
|
||||
// QString myDataDir = result.getString();
|
||||
// qDebug() << "StorageBackend: tryPeerConnect dataDir=" << myDataDir;
|
||||
|
||||
// QString peerId = m_logos->storage_module.peerId();
|
||||
|
||||
// if (peerId.isEmpty()) {
|
||||
// qDebug() << "StorageBackend: Peer ID is empty.";
|
||||
// return;
|
||||
// }
|
||||
auto result = m_logos->storage_module.connect(peerId, QStringList());
|
||||
|
||||
qDebug() << "StorageBackend: peerConnect result =" << result.value;
|
||||
// auto result = m_logos->storage_module.debug();
|
||||
|
||||
// debug("Debug " + result.getString());
|
||||
// QString filename = "test.txt";
|
||||
// QString sessionId = m_logos->storage_module.uploadInit(filename);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId;
|
||||
|
||||
// bool result = m_logos->storage_module.uploadCancel(sessionId);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadCancel result =" << result;
|
||||
}
|
||||
|
||||
void StorageBackend::tryUpload() {
|
||||
qDebug() << "StorageBackend: tryUpload called";
|
||||
|
||||
// QString filename = "test.txt";
|
||||
// m_sessionId = m_logos->storage_module.uploadInit(filename);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadInit sessionId =" << m_sessionId;
|
||||
|
||||
// QByteArray chunk = "Sample data chunk for upload.";
|
||||
// bool result = m_logos->storage_module.uploadChunk(m_sessionId, chunk);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadChunk result =" << result;
|
||||
}
|
||||
|
||||
void StorageBackend::tryUploadFinalize() {
|
||||
qDebug() << "StorageBackend: tryFinalize called";
|
||||
|
||||
// m_cid = m_logos->storage_module.uploadFinalize(m_sessionId);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadFinalize result =" << m_cid;
|
||||
|
||||
// emit cidChanged();
|
||||
}
|
||||
|
||||
void StorageBackend::tryUploadFile(const QUrl& url) {
|
||||
qDebug() << "StorageBackend: tryUploadFile called";
|
||||
qDebug() << " URL toString():" << url.toString();
|
||||
qDebug() << " URL toLocalFile():" << url.toLocalFile();
|
||||
qDebug() << " URL path():" << url.path();
|
||||
|
||||
if (!url.isLocalFile()) {
|
||||
qWarning() << "Not a local file";
|
||||
debug("The provided URL is not a local file.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset and initialize progress tracking
|
||||
m_uploadProgress = 0;
|
||||
m_uploadedBytes = 0;
|
||||
m_uploadTotalBytes = QFileInfo(url.toLocalFile()).size();
|
||||
m_uploadStatus = "Starting upload...";
|
||||
emit uploadProgressChanged();
|
||||
emit uploadStatusChanged();
|
||||
|
||||
debug(QString("Starting upload of file: %1 bytes").arg(m_uploadTotalBytes));
|
||||
|
||||
// QString filename = url.toLocalFile();
|
||||
|
||||
// // QString filename = "/home/arnaud/Work/logos/logos-storage-ui/README.md";
|
||||
// QString sessionId = m_logos->storage_module.uploadInit(filename);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId;
|
||||
|
||||
// QtConcurrent::run([this, url]() {
|
||||
// LogosResult result = m_logos->storage_module.uploadUrl(url);
|
||||
|
||||
// Go back to the main thread
|
||||
// // Better to use signal
|
||||
// QMetaObject::invokeMethod(
|
||||
// this,
|
||||
// [this, result]() {
|
||||
// if (!result.success) {
|
||||
// setStatus(m_status, result.getString());
|
||||
// return;
|
||||
// }
|
||||
|
||||
// QString sessionId = result.value.value<QString>();
|
||||
|
||||
// qDebug() << "StorageBackend: uploadFromPath result =" << sessionId;
|
||||
// },
|
||||
// Qt::QueuedConnection);
|
||||
// });
|
||||
// QTimer::singleShot(0, this, [this, url]() {
|
||||
LogosResult result = m_logos->storage_module.uploadUrl(url);
|
||||
|
||||
if (!result.success) {
|
||||
debug(result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
QString sessionId = result.value.value<QString>();
|
||||
//});
|
||||
qDebug() << "StorageBackend: tryUploadFile result =" << sessionId;
|
||||
}
|
||||
|
||||
// void StorageBackend::tryUploadFile(const QUrl& url) {
|
||||
// qDebug() << "StorageBackend:tryUploadFile called";
|
||||
|
||||
// if (!url.isLocalFile()) {
|
||||
// qWarning() << "Not a local file";
|
||||
// m_statusText = "The provided URL is not a local file.";
|
||||
// emit statusChanged();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// QString localPath = url.toLocalFile();
|
||||
// qDebug() << " Uploading from:" << localPath;
|
||||
|
||||
// QFile file(localPath);
|
||||
// if (!file.open(QIODevice::ReadOnly)) {
|
||||
// qWarning() << "Cannot open file for reading:" << localPath;
|
||||
// m_statusText = "Cannot open file for reading: " + localPath;
|
||||
// emit statusChanged();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const qint64 chunkSize = 1024 * 64; // 64KB
|
||||
// qint64 totalSize = file.size();
|
||||
// qint64 bytesRead = 0;
|
||||
|
||||
// QFileInfo fileInfo(localPath);
|
||||
// QString filename = fileInfo.fileName();
|
||||
|
||||
// LogosResult result = m_logos->storage_module.uploadInit("test.txt", chunkSize);
|
||||
|
||||
// if (!result.success) {
|
||||
// debug(result.getString());
|
||||
// file.close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// QString sessionId = result.getString();
|
||||
|
||||
// while (!file.atEnd()) {
|
||||
// QByteArray chunk = file.read(chunkSize);
|
||||
// bytesRead += chunk.size();
|
||||
|
||||
// qDebug() << " Read chunk:" << chunk.size() << "bytes"
|
||||
// << "Progress:" << bytesRead << "/" << totalSize;
|
||||
|
||||
// result = m_logos->storage_module.uploadChunk(sessionId, chunk);
|
||||
|
||||
// if (!result.success) {
|
||||
// qWarning("StorageBackend:tryUploadFile failed to send uploadChunk command");
|
||||
// file.close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // Calculate progress percentage
|
||||
// int progress = (bytesRead * 100) / totalSize;
|
||||
// qDebug() << " Progress:" << progress << "%";
|
||||
// }
|
||||
|
||||
// file.close();
|
||||
|
||||
// result = m_logos->storage_module.uploadFinalize(sessionId);
|
||||
|
||||
// if (!result.success) {
|
||||
// qWarning("StorageBackend:tryUploadFile failed to send uploadFinalize command");
|
||||
// file.close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// qDebug() << "Upload complete, CID:" << result.getString();
|
||||
|
||||
// file.close();
|
||||
// }
|
||||
|
||||
void StorageBackend::tryDownloadFile(const QString& cid, const QUrl& url) {
|
||||
qDebug() << "StorageBackend: tryDownloadFile called";
|
||||
|
||||
if (!url.isLocalFile()) {
|
||||
qWarning() << "Not a local file";
|
||||
debug("The provided URL is not a local file.");
|
||||
return;
|
||||
}
|
||||
|
||||
// QString filename = url.toLocalFile();
|
||||
|
||||
// // QString filename = "/home/arnaud/Work/logos/logos-storage-ui/README.md";
|
||||
// QString sessionId = m_logos->storage_module.uploadInit(filename);
|
||||
|
||||
// qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId;
|
||||
|
||||
LogosResult result = m_logos->storage_module.downloadToUrl(cid, url, false);
|
||||
|
||||
if (!result.success) {
|
||||
debug(result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
QString sessionId = result.value.value<QString>();
|
||||
|
||||
qDebug() << "StorageBackend: tryDownloadFile result =" << sessionId;
|
||||
}
|
||||
|
||||
void StorageBackend::exists(const QString& cid) {
|
||||
qDebug() << "StorageBackend::exists called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.exists(cid);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::exists failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Does " + cid + " exists ? " + QVariant(result.getValue<bool>()).toString());
|
||||
}
|
||||
|
||||
void StorageBackend::remove(const QString& cid) {
|
||||
qDebug() << "StorageBackend::remove called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.remove(cid);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::remove failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Cid " + cid + " removed.");
|
||||
}
|
||||
|
||||
void StorageBackend::fetch(const QString& cid) {
|
||||
qDebug() << "StorageBackend::fetch called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.fetch(cid);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::fetch failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Cid " + cid + " fetched.");
|
||||
}
|
||||
|
||||
void StorageBackend::version() {
|
||||
qDebug() << "StorageBackend::version called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.version();
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::version failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Version: " + result.getString());
|
||||
}
|
||||
|
||||
void StorageBackend::showPeerId() {
|
||||
qDebug() << "StorageBackend::peerId called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.peerId();
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::peerId failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Peer ID: " + result.getString());
|
||||
}
|
||||
|
||||
void StorageBackend::spr() {
|
||||
qDebug() << "StorageBackend::spr called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.spr();
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::spr failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("SPR: " + result.getString());
|
||||
}
|
||||
|
||||
void StorageBackend::dataDir() {
|
||||
qDebug() << "StorageBackend::dataDir called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.dataDir();
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::dataDir failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Data dir: " + result.getString());
|
||||
}
|
||||
|
||||
void StorageBackend::downloadManifest(const QString& cid) {
|
||||
qDebug() << "StorageBackend::downloadManifest called with cid=" << cid;
|
||||
|
||||
LogosResult result = m_logos->storage_module.downloadManifest(cid);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::downloadManifest failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Manifest tree cid: " + result.getString("treeCid"));
|
||||
debug(QString("Manifest datasetSize %1").arg(result.getInt("datasetSize")));
|
||||
debug(QString("Manifest blockSize %1").arg(result.getInt("blockSize")));
|
||||
debug("Manifest filename: " + result.getString("filename"));
|
||||
debug("Manifest mimetype: " + result.getString("mimetype"));
|
||||
}
|
||||
|
||||
void StorageBackend::downloadManifests() {
|
||||
qDebug() << "StorageBackend::downloadManifests called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.manifests();
|
||||
QString error = result.getError();
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::downloadManifests failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantList manifestsList = result.getList();
|
||||
int count = manifestsList.size();
|
||||
|
||||
debug(QString("Found %1 manifests").arg(count));
|
||||
|
||||
// for (const QVariant& manifestVariant : manifestsList) {
|
||||
// QVariantMap manifest = manifestVariant.toMap();
|
||||
|
||||
// QString cid = manifest["cid"].toString();
|
||||
// QString treeCid = manifest["treeCid"].toString();
|
||||
// QString filename = manifest["filename"].toString();
|
||||
// qint64 datasetSize = manifest["datasetSize"].toLongLong();
|
||||
|
||||
// debug(QString("Manifest: %1, treeCid: %2, size: %3")
|
||||
// .arg(filename)
|
||||
// .arg(treeCid.isEmpty() ? "EMPTY" : treeCid)
|
||||
// .arg(datasetSize));
|
||||
// }
|
||||
}
|
||||
|
||||
void StorageBackend::space() {
|
||||
qDebug() << "StorageBackend::space called";
|
||||
|
||||
LogosResult result = m_logos->storage_module.space();
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::space failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug(QString("Space datasetSize %1").arg(result.getInt("totalBlocks")));
|
||||
debug(QString("Space quotaMaxBytes %1").arg(result.getInt("quotaMaxBytes")));
|
||||
debug(QString("Space quotaUsedBytes %1").arg(result.getInt("quotaUsedBytes")));
|
||||
debug(QString("Space quotaReservedBytes %1").arg(result.getInt("quotaReservedBytes")));
|
||||
}
|
||||
|
||||
void StorageBackend::updateLogLevel(const QString& logLevel) {
|
||||
qDebug() << "StorageBackend::updateLogLevel called with logLevel=" << logLevel;
|
||||
|
||||
LogosResult result = m_logos->storage_module.updateLogLevel(logLevel);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::updateLogLevel failed with error=" + result.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Log level updated to " + logLevel);
|
||||
}
|
||||
|
||||
StorageBackend::StorageStatus StorageBackend::status() const { return m_status; }
|
||||
|
||||
QString StorageBackend::cid() const { return m_cid; }
|
||||
|
||||
QString StorageBackend::configJson() const { return m_configJson; }
|
||||
|
||||
int StorageBackend::uploadProgress() const { return m_uploadProgress; }
|
||||
|
||||
QString StorageBackend::uploadStatus() const { return m_uploadStatus; }
|
||||
|
||||
void StorageBackend::reloadIfChanged(const QString& configJson) {
|
||||
if (configJson == m_configJson) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("New config detected");
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(configJson.toUtf8());
|
||||
if (doc.isNull()) {
|
||||
debug("Invalid json detected !");
|
||||
|
||||
m_configJson = configJson;
|
||||
emit configJsonChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_status == StorageStatus::Running || m_status == StorageStatus::Stopping ||
|
||||
m_status == StorageStatus::Starting) {
|
||||
debug("Cannot reload the config while running, stopping or starting...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_status == StorageStatus::Stopped) {
|
||||
LogosResult result = m_logos->storage_module.destroy();
|
||||
|
||||
if (!result.success) {
|
||||
debug("Failed to destroy the context error=" + result.getError());
|
||||
return;
|
||||
} else {
|
||||
setStatus(StorageStatus::Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
bool result = m_logos->storage_module.init(configJson);
|
||||
|
||||
if (!result) {
|
||||
debug("Failed to init context with new config, will rollback.");
|
||||
|
||||
bool result = m_logos->storage_module.init(m_configJson);
|
||||
|
||||
if (!result) {
|
||||
debug("Failed to init context with old config, that's a serious issue.");
|
||||
} else {
|
||||
debug("Old config restored");
|
||||
setStatus(StorageStatus::Stopped);
|
||||
|
||||
m_configJson = configJson;
|
||||
emit configJsonChanged();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
debug("New config loaded successfully");
|
||||
|
||||
m_configJson = configJson;
|
||||
setStatus(StorageStatus::Stopped);
|
||||
}
|
||||
|
||||
@ -8,47 +8,80 @@
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
static const int RET_OK = 0;
|
||||
static const int RET_PROGRESS = 3;
|
||||
|
||||
class StorageBackend : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(QString debugLogs READ debugLogs NOTIFY debugLogsChanged)
|
||||
Q_PROPERTY(StorageStatus status READ status NOTIFY statusChanged)
|
||||
Q_PROPERTY(QString cid READ cid NOTIFY cidChanged)
|
||||
Q_PROPERTY(QString configJson READ configJson NOTIFY configJsonChanged)
|
||||
Q_PROPERTY(int uploadProgress READ uploadProgress NOTIFY uploadProgressChanged)
|
||||
Q_PROPERTY(QString uploadStatus READ uploadStatus NOTIFY uploadStatusChanged)
|
||||
|
||||
public:
|
||||
enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed };
|
||||
Q_ENUM(StorageStatus)
|
||||
|
||||
Q_PROPERTY(bool canStartStop READ canStartStop NOTIFY statusChanged)
|
||||
bool canStartStop() const;
|
||||
|
||||
Q_PROPERTY(QString startStopText READ startStopText NOTIFY statusChanged)
|
||||
QString startStopText() const;
|
||||
|
||||
Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged)
|
||||
QString statusText() const;
|
||||
QString cid() const;
|
||||
QString debugLogs() const;
|
||||
StorageStatus status() const;
|
||||
QString configJson() const;
|
||||
int uploadProgress() const;
|
||||
QString uploadStatus() const;
|
||||
|
||||
explicit StorageBackend(LogosAPI* logosAPI = nullptr, QObject* parent = nullptr);
|
||||
~StorageBackend();
|
||||
|
||||
public slots:
|
||||
void startStop();
|
||||
LogosResult start(const QString& configJson = "");
|
||||
void destroy();
|
||||
bool isRunning();
|
||||
bool isInitialised();
|
||||
void stop();
|
||||
void tryPeerConnect(const QString& peerId);
|
||||
void tryDebug();
|
||||
void tryUpload();
|
||||
void tryUploadFinalize();
|
||||
void exists(const QString& cid);
|
||||
void remove(const QString& cid);
|
||||
void fetch(const QString& cid);
|
||||
void tryUploadFile(const QUrl& url);
|
||||
void tryDownloadFile(const QString& cid, const QUrl& url);
|
||||
void dataDir();
|
||||
void version();
|
||||
void spr();
|
||||
void showPeerId();
|
||||
void downloadManifest(const QString& cid);
|
||||
void downloadManifests();
|
||||
void space();
|
||||
LogosResult init(const QString& configJson);
|
||||
void updateLogLevel(const QString& logLevel);
|
||||
|
||||
signals:
|
||||
void statusChanged();
|
||||
void debugLogsChanged();
|
||||
void stopped();
|
||||
void cidChanged();
|
||||
void configJsonChanged();
|
||||
void uploadProgressChanged();
|
||||
void uploadStatusChanged();
|
||||
|
||||
private slots:
|
||||
|
||||
private:
|
||||
void setStatus(StorageStatus newStatus, QString statusText);
|
||||
void initStorage();
|
||||
void setStatus(StorageStatus newStatus);
|
||||
void peerConnect(const QString& peerId);
|
||||
void debug(const QString& log);
|
||||
void reloadIfChanged(const QString& configJson);
|
||||
|
||||
StorageStatus m_status;
|
||||
LogosAPI* m_logosAPI;
|
||||
LogosModules* m_logos;
|
||||
|
||||
QString m_statusText;
|
||||
StorageStatus m_status;
|
||||
QString m_debugLogs;
|
||||
QString m_cid;
|
||||
QString m_configJson;
|
||||
int m_uploadProgress = 0;
|
||||
QString m_uploadStatus = "";
|
||||
qint64 m_uploadTotalBytes = 0;
|
||||
qint64 m_uploadedBytes = 0;
|
||||
};
|
||||
|
||||
@ -31,6 +31,35 @@ QWidget* StorageUIPlugin::createWidget(LogosAPI* logosAPI) {
|
||||
|
||||
root->setProperty("backend", QVariant::fromValue(static_cast<QObject*>(backend)));
|
||||
|
||||
QFileInfo info("config.json");
|
||||
QString configJson = "{}";
|
||||
|
||||
if (info.exists() && info.isFile()) {
|
||||
qDebug() << "StorageUIPlugin: config.json is found, let's try to load it...";
|
||||
|
||||
QFile file("config.json");
|
||||
if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
configJson = QString::fromUtf8(file.readAll());
|
||||
|
||||
qDebug() << "StorageUIPlugin: config.json is found, let's try to load it... configJson=" << configJson;
|
||||
} else {
|
||||
qDebug() << "StorageUIPlugin: Failed to load config.json";
|
||||
}
|
||||
}
|
||||
|
||||
LogosResult result = backend->init(configJson);
|
||||
|
||||
if (!result.success) {
|
||||
QString error = result.getError();
|
||||
qWarning() << "StorageUIPlugin: Failed to init backend, will use mock version:" << error;
|
||||
} else {
|
||||
result = backend->start();
|
||||
|
||||
if (!result.success) {
|
||||
qWarning() << "StorageUIPlugin: Failed to init backend, will use mock version:" << result.getError();
|
||||
}
|
||||
}
|
||||
|
||||
return quickWidget;
|
||||
}
|
||||
|
||||
@ -66,13 +95,13 @@ void StorageUIPlugin::destroyWidget(QWidget* widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!backend->isInitialised()) {
|
||||
if (backend->status() != StorageBackend::StorageStatus::Destroyed) {
|
||||
qDebug() << "StorageUIPlugin::destroyWidget: backend is not initialised so let's detroy it.";
|
||||
quickWidget->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!backend->isRunning()) {
|
||||
if (backend->status() == StorageBackend::StorageStatus::Running) {
|
||||
qDebug() << "StorageUIPlugin::destroyWidget: backend is not running so let's detroy it.";
|
||||
|
||||
backend->destroy();
|
||||
|
||||
@ -74,6 +74,7 @@ add_library(storage_generated STATIC
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.cpp
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.cpp
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.cpp
|
||||
${LOGOS_CPP_SDK_ROOT}/cpp/logos_types.cpp
|
||||
)
|
||||
|
||||
# Define the dependencies needed for storage_generated
|
||||
|
||||
@ -1,63 +1,592 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 400
|
||||
height: 700
|
||||
color: "#000000"
|
||||
|
||||
//import QtQuick.Layouts
|
||||
Item {
|
||||
property var backend: mockBackend
|
||||
readonly property int stopped: 0
|
||||
readonly property int starting: 1
|
||||
readonly property int running: 2
|
||||
readonly property int stopping: 3
|
||||
readonly property int destroyed: 4
|
||||
property string peerId: ""
|
||||
property string downloadDestination: ""
|
||||
property url downloadCid: ""
|
||||
property string logLevel: ""
|
||||
property bool showDebug: false
|
||||
property url uploadCid: root.backend.cid
|
||||
property url configJson: root.backend.configJson
|
||||
|
||||
id: root
|
||||
width: 400
|
||||
height: 300
|
||||
function getStatusLabel() {
|
||||
switch (backend.status) {
|
||||
case stopped:
|
||||
return "Logos Storage stopped."
|
||||
case starting:
|
||||
return "Logos Storage is starting..."
|
||||
case running:
|
||||
return "Logos Storage started."
|
||||
case stopping:
|
||||
return "Logos Storage is stopping..."
|
||||
case destroyed:
|
||||
return "Logos Storage is not initialised."
|
||||
}
|
||||
}
|
||||
|
||||
function startStopText() {
|
||||
if (backend.status == running) {
|
||||
return "Stop"
|
||||
}
|
||||
return "Start"
|
||||
}
|
||||
|
||||
function canStartStop() {
|
||||
return backend.status == running || backend.status == stopped
|
||||
}
|
||||
|
||||
function isRunning() {
|
||||
return backend.status == running
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: mockBackend
|
||||
|
||||
property var status: root.stopped
|
||||
property var statusText: "Destroyed"
|
||||
property var startStopText: "Start"
|
||||
property var canStartStop: true
|
||||
property var debugLogs: "Hello !"
|
||||
property var configJson: "{}"
|
||||
property url cid: ""
|
||||
property string uploadStatus: ""
|
||||
property int uploadProgress: 0
|
||||
|
||||
function startStop() {
|
||||
if (status == root.running) {
|
||||
status = root.stopped
|
||||
statusText = "Stopped"
|
||||
startStopText = "Start"
|
||||
} else {
|
||||
status = root.running
|
||||
statusText = "Started"
|
||||
startStopText = "Stop"
|
||||
function start(newConfigJson) {
|
||||
status = root.running
|
||||
}
|
||||
|
||||
function stop() {
|
||||
status = root.stopped
|
||||
}
|
||||
|
||||
function tryPeerConnect(peerId) {
|
||||
console.log("Attempting peer connection...")
|
||||
}
|
||||
|
||||
function tryDebug() {
|
||||
console.log("Attempting peer connection...")
|
||||
}
|
||||
|
||||
function spr() {}
|
||||
|
||||
function showPeerId() {}
|
||||
|
||||
function version() {}
|
||||
|
||||
function dataDir() {}
|
||||
|
||||
function tryUploadFinalize() {
|
||||
console.log("Attempting upload finalize")
|
||||
}
|
||||
|
||||
function tryUploadFile(file) {
|
||||
console.log("Attempting upload file")
|
||||
}
|
||||
|
||||
function tryDownloadFile(cid, file) {
|
||||
console.log("Attempting download a file", cid, file)
|
||||
}
|
||||
|
||||
function exists(cid) {
|
||||
console.log("Attempting exists", cid)
|
||||
}
|
||||
|
||||
function fetch(cid) {
|
||||
console.log("Attempting fetch", cid)
|
||||
}
|
||||
|
||||
function remove(cid) {
|
||||
console.log("Attempting remove", cid)
|
||||
}
|
||||
|
||||
function downloadManifest(cid) {
|
||||
console.log("Attempting downloadManifest", cid)
|
||||
}
|
||||
|
||||
function downloadManifests() {
|
||||
console.log("Attempting downloadManifests")
|
||||
}
|
||||
|
||||
function space() {}
|
||||
|
||||
function updateLogLevel(logLevel) {}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: statusTextElement
|
||||
objectName: "status"
|
||||
text: root.getStatusLabel()
|
||||
color: "white"
|
||||
font.pointSize: 20
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
id: startStopButton
|
||||
objectName: "startStopButton"
|
||||
anchors.leftMargin: 50
|
||||
text: root.startStopText()
|
||||
enabled: root.canStartStop()
|
||||
onClicked: root.backend.status == root.stopped ? root.backend.start(
|
||||
jsonEditor.text) : root.backend.stop()
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: statusTextElement.bottom
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: cidTextEdit
|
||||
objectName: "cid"
|
||||
color: "white"
|
||||
font.pointSize: 14
|
||||
readOnly: true
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: startStopButton.bottom
|
||||
anchors.topMargin: 10
|
||||
text: root.uploadCid
|
||||
}
|
||||
|
||||
Button {
|
||||
id: openFile
|
||||
text: "Open file"
|
||||
onClicked: fileDialog.open()
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: cidTextEdit.bottom
|
||||
anchors.topMargin: 15
|
||||
enabled: root.isRunning
|
||||
}
|
||||
|
||||
Column {
|
||||
id: uploadProgressColumn
|
||||
anchors.top: openFile.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 300
|
||||
spacing: 5
|
||||
visible: root.backend.uploadProgress > 0
|
||||
|
||||
ProgressBar {
|
||||
width: parent.width
|
||||
value: root.backend.uploadProgress / 100.0
|
||||
|
||||
background: Rectangle {
|
||||
color: "#333333"
|
||||
radius: 3
|
||||
implicitWidth: 300
|
||||
implicitHeight: 6
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: 300
|
||||
implicitHeight: 6
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * parent.parent.visualPosition
|
||||
height: parent.height
|
||||
radius: 3
|
||||
color: "#4CAF50"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.backend.uploadStatus
|
||||
color: "#888888"
|
||||
font.pixelSize: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: peerIdField
|
||||
placeholderText: "Enter the peer Id"
|
||||
placeholderTextColor: "#999999"
|
||||
color: "#000000"
|
||||
selectByMouse: true
|
||||
text: root.peerId
|
||||
onTextChanged: root.peerId = text
|
||||
anchors.top: uploadProgressColumn.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
id: peerConnectButton
|
||||
objectName: "peerConnectButton"
|
||||
text: "Peer connect"
|
||||
onClicked: root.backend.tryPeerConnect(root.peerId)
|
||||
anchors.top: peerIdField.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: debugButton
|
||||
objectName: "debugButton"
|
||||
text: "Debug"
|
||||
onClicked: root.backend.tryDebug()
|
||||
anchors.top: peerConnectButton.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 50
|
||||
}
|
||||
|
||||
Button {
|
||||
id: peerIdButton
|
||||
objectName: "peerIdButton"
|
||||
text: "Peer Id"
|
||||
onClicked: root.backend.showPeerId()
|
||||
anchors.top: peerConnectButton.bottom
|
||||
anchors.right: debugButton.left
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 50
|
||||
}
|
||||
|
||||
Button {
|
||||
id: dataDirButton
|
||||
objectName: "dataDirButton"
|
||||
text: "Data dir"
|
||||
onClicked: root.backend.dataDir()
|
||||
anchors.top: peerConnectButton.bottom
|
||||
anchors.right: peerIdButton.left
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 50
|
||||
}
|
||||
|
||||
Button {
|
||||
id: sprButton
|
||||
objectName: "sprButton"
|
||||
text: "SPR"
|
||||
onClicked: root.backend.spr()
|
||||
anchors.top: peerConnectButton.bottom
|
||||
anchors.left: debugButton.right
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 50
|
||||
}
|
||||
|
||||
Button {
|
||||
id: versionButton
|
||||
objectName: "versionButton"
|
||||
text: "Version"
|
||||
onClicked: root.backend.version()
|
||||
anchors.top: peerConnectButton.bottom
|
||||
anchors.left: sprButton.right
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 50
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: cidDownloadField
|
||||
placeholderTextColor: "#999999"
|
||||
placeholderText: "Enter the cid to download"
|
||||
color: "black"
|
||||
// text: root.downloadCid
|
||||
onTextChanged: root.downloadCid = text
|
||||
anchors.top: debugButton.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
id: openFile2
|
||||
text: "Open file"
|
||||
onClicked: fileDialog2.open()
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: cidDownloadField.bottom
|
||||
anchors.topMargin: 15
|
||||
enabled: root.isRunning
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cidDownloadButton
|
||||
objectName: "cidDownloadButton"
|
||||
text: "Download"
|
||||
onClicked: root.backend.tryDownloadFile(root.downloadCid,
|
||||
root.downloadDestination)
|
||||
anchors.top: openFile2.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: existsButton
|
||||
objectName: "existsButton"
|
||||
text: "Exists"
|
||||
onClicked: root.backend.exists(root.downloadCid)
|
||||
anchors.top: openFile2.bottom
|
||||
anchors.left: cidDownloadButton.right
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: fetchButton
|
||||
objectName: "fetchButton"
|
||||
text: "Fetch"
|
||||
onClicked: root.backend.fetch(root.downloadCid)
|
||||
anchors.top: openFile2.bottom
|
||||
anchors.left: existsButton.right
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: removeButton
|
||||
objectName: "removeButton"
|
||||
text: "Remove"
|
||||
onClicked: root.backend.remove(root.downloadCid)
|
||||
anchors.top: openFile2.bottom
|
||||
anchors.right: cidDownloadButton.left
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadManifestButton
|
||||
objectName: "downloadManifestButton"
|
||||
text: "Download manifest"
|
||||
onClicked: root.backend.downloadManifest(root.downloadCid)
|
||||
anchors.top: openFile2.bottom
|
||||
anchors.right: removeButton.left
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadManifestsButton
|
||||
objectName: "downloadManifestsButton"
|
||||
text: "Manifests"
|
||||
onClicked: root.backend.downloadManifests()
|
||||
anchors.top: cidDownloadButton.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
Button {
|
||||
id: spaceButton
|
||||
objectName: "spaceButton"
|
||||
text: "Space"
|
||||
onClicked: root.backend.space()
|
||||
anchors.top: cidDownloadButton.bottom
|
||||
anchors.right: downloadManifestsButton.left
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: logLevelField
|
||||
placeholderTextColor: "#999999"
|
||||
placeholderText: "Enter the log level to download"
|
||||
color: "black"
|
||||
// text: root.downloadCid
|
||||
onTextChanged: root.logLevel = text
|
||||
anchors.top: downloadManifestsButton.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
id: logLevelButton
|
||||
objectName: "logLevelButton"
|
||||
text: "Log level"
|
||||
onClicked: root.backend.updateLogLevel(root.logLevel)
|
||||
anchors.top: logLevelField.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
enabled: root.isRunning
|
||||
anchors.topMargin: 10
|
||||
}
|
||||
|
||||
// TextEdit {
|
||||
// id: selectableText
|
||||
// anchors.fill: parent
|
||||
// anchors.margins: 10
|
||||
// text: "This text is selectable. You can copy it, but not edit it."
|
||||
// readOnly: true // Makes the text non-editable
|
||||
// selectByMouse: true // Enables selection by mouse drag (often the default for desktop)
|
||||
// // Optional: Change cursor shape to IBeam when hovering
|
||||
// MouseArea {
|
||||
// anchors.fill: parent
|
||||
// cursorShape: Qt.IBeamCursor
|
||||
// acceptedButtons: Qt.NoButton // Allows TextEdit to handle mouse events
|
||||
// }
|
||||
// }
|
||||
|
||||
// Button {
|
||||
// anchors.left: parent.left
|
||||
// anchors.bottom: parent.bottom
|
||||
// objectName: "uploadButton"
|
||||
// text: "Upload"
|
||||
// anchors.bottomMargin: 80
|
||||
// onClicked: root.backend.tryUpload()
|
||||
// }
|
||||
|
||||
// Button {
|
||||
// anchors.left: parent.left
|
||||
// anchors.bottom: parent.bottom
|
||||
// objectName: "finalizeButton"
|
||||
// text: "Finalize"
|
||||
// onClicked: root.backend.tryUploadFinalize()
|
||||
// }
|
||||
// Button {
|
||||
// anchors.left: parent.left
|
||||
// anchors.bottom: parent.bottom
|
||||
// objectName: "uploadFileButton"
|
||||
// text: "Upload file"
|
||||
// onClicked: root.backend.tryUploadFile()
|
||||
// anchors.bottomMargin: 30
|
||||
// }
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
onAccepted: root.backend.tryUploadFile(fileDialog.selectedFile)
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: fileDialog2
|
||||
fileMode: FileDialog.SaveFile
|
||||
onAccepted: {
|
||||
root.downloadDestination = fileDialog2.selectedFile
|
||||
console.log("Destination selected:",
|
||||
root.backend.downloadDestination)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 0
|
||||
anchors.rightMargin: 0
|
||||
anchors.topMargin: 0
|
||||
anchors.bottomMargin: 0
|
||||
color: "#202428"
|
||||
}
|
||||
id: debugPanel
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 150
|
||||
color: "#111111"
|
||||
visible: root.showDebug // or: visible: showDebug
|
||||
|
||||
Text {
|
||||
objectName: "status"
|
||||
text: root.backend.statusText
|
||||
color: "white"
|
||||
font.pointSize: 20
|
||||
anchors.centerIn: parent
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
TabBar {
|
||||
id: bar
|
||||
width: parent.width
|
||||
|
||||
Button {
|
||||
objectName: "startStopButton"
|
||||
anchors.leftMargin: 50
|
||||
text: root.backend.startStopText
|
||||
enabled: root.backend.canStartStop
|
||||
onClicked: root.backend.startStop()
|
||||
TabButton {
|
||||
text: qsTr("Logs")
|
||||
}
|
||||
|
||||
TabButton {
|
||||
text: qsTr("Config")
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackLayout
|
||||
currentIndex: bar.currentIndex
|
||||
anchors.top: bar.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
Item {
|
||||
id: homeTab
|
||||
|
||||
Flickable {
|
||||
id: flick
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
contentWidth: width
|
||||
contentHeight: debugText.paintedHeight
|
||||
|
||||
TextEdit {
|
||||
id: debugText
|
||||
width: flick.width
|
||||
text: root.backend.debugLogs
|
||||
color: "#dddddd"
|
||||
font.family: "monospace"
|
||||
font.pixelSize: 12
|
||||
wrapMode: Text.WrapAnywhere
|
||||
readOnly: true
|
||||
|
||||
onTextChanged: Qt.callLater(function () {
|
||||
flick.contentY = Math.max(
|
||||
0, flick.contentHeight - flick.height)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: discoverTab
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
|
||||
TextArea {
|
||||
id: jsonEditor
|
||||
font.family: "monospace"
|
||||
font.pixelSize: 12
|
||||
color: "#d4d4d4"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
background: Rectangle {
|
||||
color: "#1e1e1e"
|
||||
border.color: jsonEditor.isValid ? "#3a3a3a" : "#ff0000"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
property bool isValid: true
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
|
||||
function onConfigJsonChanged() {
|
||||
jsonEditor.text = root.backend.configJson
|
||||
try {
|
||||
const jsonData = JSON.parse(jsonEditor.text)
|
||||
jsonEditor.isValid = true
|
||||
} catch (e) {
|
||||
jsonEditor.isValid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
text = root.backend.configJson
|
||||
|
||||
try {
|
||||
const jsonData = JSON.parse(text)
|
||||
isValid = true
|
||||
} catch (e) {
|
||||
isValid = false
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
try {
|
||||
const jsonData = JSON.parse(text)
|
||||
isValid = true
|
||||
} catch (e) {
|
||||
isValid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Shortcut {
|
||||
sequence: "Ctrl+D"
|
||||
onActivated: root.showDebug = !root.showDebug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/logos-cpp-sdk
vendored
2
vendor/logos-cpp-sdk
vendored
@ -1 +1 @@
|
||||
Subproject commit 32f1d7080d784ff044d91d076ef2f0c7305d4784
|
||||
Subproject commit c3477d29e32cae5f73ca637fb81e547f8a6cba58
|
||||
2
vendor/logos-liblogos
vendored
2
vendor/logos-liblogos
vendored
@ -1 +1 @@
|
||||
Subproject commit fb7a9d6888dc59dd29437e8d3a2d38fc9f0e8696
|
||||
Subproject commit 1378757dc8745941ebee79ae484abe62be2f5db4
|
||||
2
vendor/logos-storage-module
vendored
2
vendor/logos-storage-module
vendored
@ -1 +1 @@
|
||||
Subproject commit e01d9dbc6159bf6442a670e9432714b024b7698b
|
||||
Subproject commit 7dceb6a8dfd5a5bbd47dc9b00e55f80b62ab1e6e
|
||||
2
vendor/logos-storage-nim
vendored
2
vendor/logos-storage-nim
vendored
@ -1 +1 @@
|
||||
Subproject commit 7d51740f91c0ee3781d40111787f0d450bf729ae
|
||||
Subproject commit e375223500ca0fd919b0e504eab65c6ddb5e4233
|
||||
Loading…
x
Reference in New Issue
Block a user