logos-storage-app-skeleton/src/StorageUIPlugin.cpp

175 lines
5.8 KiB
C++
Raw Normal View History

2026-01-30 21:15:18 +04:00
#include "StorageUIPlugin.h"
#include "StorageBackend.h"
2026-02-17 11:27:03 +04:00
#include <QCoreApplication>
2026-01-30 21:15:18 +04:00
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickWidget>
2026-02-17 11:27:03 +04:00
#include <QSettings>
2026-01-30 21:15:18 +04:00
QWidget* StorageUIPlugin::createWidget(LogosAPI* logosAPI) {
qDebug() << "StorageUIPlugin::createWidget called";
2026-02-17 11:27:03 +04:00
QCoreApplication::setOrganizationName("Logos");
QCoreApplication::setOrganizationDomain("logos.co");
QCoreApplication::setApplicationName("LogosStorage");
2026-01-30 21:15:18 +04:00
QQuickWidget* quickWidget = new QQuickWidget();
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
2026-02-17 11:27:03 +04:00
// Add import path for Logos QML modules (Logos.Theme, Logos.Controls)
QQmlEngine* engine = quickWidget->engine();
QString qmlModulesPath = QCoreApplication::applicationDirPath() + "/../lib";
engine->addImportPath(qmlModulesPath);
qDebug() << "StorageUIPlugin: Loading settings...";
QSettings settings("Logos", "LogosStorage");
int discoveryPort = settings.value("Storage/discoveryPort", 0).toInt();
int tcpPort = settings.value("Storage/tcpPort", 0).toInt();
QString dataDir = settings.value("Storage/dataDir", "").toString();
bool onboardingCompleted = settings.value("Storage/onboardingCompleted", false).toBool();
qDebug() << "StorageUIPlugin: Settings Loaded onboardingCompleted=" << onboardingCompleted;
qDebug() << "StorageUIPlugin: Settings Loaded dataDir=" << dataDir;
qDebug() << "StorageUIPlugin: Settings Loaded discoveryPort=" << discoveryPort;
qDebug() << "StorageUIPlugin: Settings Loaded tcpPort=" << tcpPort;
QString qmlPath = "qrc:/Main.qml";
// Create backend instance
StorageBackend* backend = new StorageBackend(logosAPI, quickWidget);
if (onboardingCompleted) {
qmlPath = "qrc:/StorageView.qml";
}
qDebug() << "StorageUIPlugin: qmlPath=" << qmlPath;
2026-01-30 21:15:18 +04:00
quickWidget->setSource(QUrl(qmlPath));
if (quickWidget->status() == QQuickWidget::Error) {
qWarning() << "StorageUIPlugin: Failed to load QML:" << quickWidget->errors();
}
// Set backend as context property
QQuickItem* root = quickWidget->rootObject();
Q_ASSERT(root);
root->setProperty("backend", QVariant::fromValue(static_cast<QObject*>(backend)));
2026-02-13 20:16:27 +04:00
QString configJson = "{}";
2026-02-17 11:27:03 +04:00
if (onboardingCompleted) {
configJson = backend->buildConfig(dataDir, discoveryPort, tcpPort);
}
2026-02-13 20:16:27 +04:00
2026-02-17 11:27:03 +04:00
QFileInfo info("config.json");
2026-02-13 20:16:27 +04:00
2026-02-17 11:27:03 +04:00
if (info.exists() && info.isFile()) {
qWarning()
<< "StorageUIPlugin: config.json is found ! It will override the configuration loaded by the onboarding !";
configJson = backend->buildConfigFromFile("config.json");
2026-02-13 20:16:27 +04:00
}
2026-02-17 11:27:03 +04:00
qDebug() << "StorageUIPlugin: configuration loaded configLoaded=" << configJson;
2026-02-13 20:16:27 +04:00
LogosResult result = backend->init(configJson);
if (!result.success) {
QString error = result.getError();
qWarning() << "StorageUIPlugin: Failed to init backend, will use mock version:" << error;
2026-02-17 11:27:03 +04:00
} else if (onboardingCompleted) {
LogosResult result = backend->start();
2026-02-13 20:16:27 +04:00
if (!result.success) {
2026-02-17 11:27:03 +04:00
qWarning() << "StorageUIPlugin: Failed to start the Storage Module.";
2026-02-13 20:16:27 +04:00
}
}
2026-01-30 21:15:18 +04:00
return quickWidget;
}
// Destroy the widget and clean up the backend.
// It will block the event loop up to 2 seconds to ensure proper cleanup.
// It will try to stop the backend if it is running.`
void StorageUIPlugin::destroyWidget(QWidget* widget) {
qDebug() << "StorageUIPlugin: Destroy widget";
auto* quickWidget = qobject_cast<QQuickWidget*>(widget);
if (!quickWidget) {
delete widget;
return;
}
QQuickItem* root = quickWidget->rootObject();
if (!root) {
qWarning() << "StorageUIPlugin::destroyWidget: No rootObject, deleting widget";
quickWidget->deleteLater();
return;
}
// Disable QML to ensure that not updated are pushed in the UI
root->setEnabled(false);
// Retrieve the backend object from the root element
// as it was set in createWidget
QObject* value = root->property("backend").value<QObject*>();
auto* backend = qobject_cast<StorageBackend*>(value);
if (!backend) {
qWarning() << "StorageUIPlugin::destroyWidget: No backend found on root property 'backend'.";
quickWidget->deleteLater();
return;
}
2026-02-13 20:16:27 +04:00
if (backend->status() != StorageBackend::StorageStatus::Destroyed) {
2026-01-30 21:15:18 +04:00
qDebug() << "StorageUIPlugin::destroyWidget: backend is not initialised so let's detroy it.";
quickWidget->deleteLater();
return;
}
2026-02-13 20:16:27 +04:00
if (backend->status() == StorageBackend::StorageStatus::Running) {
2026-01-30 21:15:18 +04:00
qDebug() << "StorageUIPlugin::destroyWidget: backend is not running so let's detroy it.";
backend->destroy();
quickWidget->deleteLater();
return;
}
qDebug() << "StorageUIPlugin::destroyWidget: backend is running so let's stop it.";
// Here we create a QEventLoop to wait for the stopped signal
QEventLoop loop;
QTimer timeout;
// Single shot means that the timer will only fire once.
timeout.setSingleShot(true);
// Connect to timeout and unblock the event loop after 2 seconds
QObject::connect(&timeout, &QTimer::timeout, &loop, [&]() {
qWarning() << "StorageUIPlugin::destroyWidget: stop timeout";
loop.quit();
});
// Connect to stop signal
2026-02-17 11:27:03 +04:00
QObject::connect(backend, &StorageBackend::stopCompleted, &loop, [&]() { loop.quit(); }, Qt::QueuedConnection);
2026-01-30 21:15:18 +04:00
// Call the stop method asynchronously
QMetaObject::invokeMethod(backend, "stop", Qt::QueuedConnection);
// Set the timeout to 2 sec
timeout.start(2000);
// Block
loop.exec();
// Try to cleanup, event if the stop method failed
backend->destroy();
delete quickWidget;
}