This commit is contained in:
Arnaud 2026-01-12 18:58:51 +04:00
parent ba4214d872
commit 067af5f944
No known key found for this signature in database
GPG Key ID: 20E40A5D3110766F
15 changed files with 1114 additions and 1 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.DS_Store
result
data/

272
CMakeLists.txt Normal file
View File

@ -0,0 +1,272 @@
cmake_minimum_required(VERSION 3.16)
project(StorageUIPlugin VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
# Allow override from environment or command line
if(NOT DEFINED LOGOS_LIBLOGOS_ROOT)
set(_parent_liblogos "${CMAKE_SOURCE_DIR}/../logos-liblogos")
set(_use_vendor ${LOGOS_STORAGE_UI_USE_VENDOR})
if(NOT _use_vendor)
if(NOT EXISTS "${_parent_liblogos}/interface.h")
set(_use_vendor ON)
endif()
endif()
if(_use_vendor)
set(LOGOS_LIBLOGOS_ROOT "${CMAKE_SOURCE_DIR}/vendor/logos-liblogos")
else()
set(LOGOS_LIBLOGOS_ROOT "${_parent_liblogos}")
endif()
endif()
if(NOT DEFINED LOGOS_CPP_SDK_ROOT)
set(_parent_cpp_sdk "${CMAKE_SOURCE_DIR}/../logos-cpp-sdk")
set(_use_vendor ${LOGOS_STORAGE_UI_USE_VENDOR})
if(NOT _use_vendor)
if(NOT EXISTS "${_parent_cpp_sdk}/cpp/logos_api.h")
set(_use_vendor ON)
endif()
endif()
if(_use_vendor)
set(LOGOS_CPP_SDK_ROOT "${CMAKE_SOURCE_DIR}/vendor/logos-cpp-sdk")
else()
set(LOGOS_CPP_SDK_ROOT "${_parent_cpp_sdk}")
endif()
endif()
# Check if dependencies are available (support both source and installed layouts)
set(_liblogos_found FALSE)
if(EXISTS "${LOGOS_LIBLOGOS_ROOT}/interface.h")
set(_liblogos_found TRUE)
set(_liblogos_is_source TRUE)
elseif(EXISTS "${LOGOS_LIBLOGOS_ROOT}/include/interface.h")
set(_liblogos_found TRUE)
set(_liblogos_is_source FALSE)
endif()
set(_cpp_sdk_found FALSE)
if(EXISTS "${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h")
set(_cpp_sdk_found TRUE)
set(_cpp_sdk_is_source TRUE)
elseif(EXISTS "${LOGOS_CPP_SDK_ROOT}/include/cpp/logos_api.h")
set(_cpp_sdk_found TRUE)
set(_cpp_sdk_is_source FALSE)
endif()
if(NOT _liblogos_found)
message(FATAL_ERROR "logos-liblogos not found at ${LOGOS_LIBLOGOS_ROOT}. "
"Set LOGOS_LIBLOGOS_ROOT or run git submodule update --init --recursive.")
endif()
if(NOT _cpp_sdk_found)
message(FATAL_ERROR "logos-cpp-sdk not found at ${LOGOS_CPP_SDK_ROOT}. "
"Set LOGOS_CPP_SDK_ROOT or run git submodule update --init --recursive.")
endif()
# Find Qt packages
find_package(Qt6 REQUIRED COMPONENTS Core Widgets RemoteObjects)
# Get the real path to handle symlinks correctly
get_filename_component(REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
# Try to find the component-interfaces package first
find_package(component-interfaces QUIET)
# If not found, use the local interfaces folder
if(NOT component-interfaces_FOUND)
# Include the local interfaces directory
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces)
# Create a component-interfaces library
add_library(component-interfaces INTERFACE)
target_include_directories(component-interfaces INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/interfaces)
endif()
# Source files
set(SOURCES
StorageUIComponent.cpp
StorageUIComponent.h
src/StorageWidget.cpp
src/StorageWidget.h
src/StorageWindow.cpp
src/StorageWindow.h
src/main.cpp
)
# Add SDK sources (only if source layout, installed layout uses the library)
if(_cpp_sdk_is_source)
list(APPEND SOURCES
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api.h
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_client.h
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.h
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.h
${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.h
${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.cpp
${LOGOS_CPP_SDK_ROOT}/cpp/module_proxy.h
)
endif()
# Run Logos C++ generator on metadata before compilation (only for source layout)
set(METADATA_JSON "${CMAKE_CURRENT_SOURCE_DIR}/metadata.json")
# Only run generator for source layout - nix builds already have generated files
if(_cpp_sdk_is_source)
# Source layout: build and run the generator
# Generate into build directory
set(PLUGINS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated_code")
set(CPP_GENERATOR_BUILD_DIR "${LOGOS_CPP_SDK_ROOT}/../build/cpp-generator")
set(CPP_GENERATOR "${CPP_GENERATOR_BUILD_DIR}/bin/logos-cpp-generator")
if(NOT TARGET cpp_generator_build)
add_custom_target(cpp_generator_build
COMMAND bash "${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh"
WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.."
COMMENT "Building logos-cpp-generator via ${LOGOS_CPP_SDK_ROOT}/cpp-generator/compile.sh"
VERBATIM
)
endif()
add_custom_target(run_cpp_generator_storage_ui
COMMAND "${CPP_GENERATOR}" --metadata "${METADATA_JSON}" --general-only --output-dir "${PLUGINS_OUTPUT_DIR}"
WORKING_DIRECTORY "${LOGOS_CPP_SDK_ROOT}/.."
COMMENT "Running logos-cpp-generator on ${METADATA_JSON} with output-dir ${PLUGINS_OUTPUT_DIR}"
VERBATIM
)
add_dependencies(run_cpp_generator_storage_ui cpp_generator_build)
# Add generated logos_sdk.cpp - will be generated by run_cpp_generator_storage_ui
list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp)
# Mark as generated so CMake knows to wait for it
set_source_files_properties(
${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp
PROPERTIES GENERATED TRUE
)
else()
# Installed/nix layout: files are already in source tree from lib.nix preConfigure
# lib.nix creates ./generated_code in source directory before CMake runs
set(PLUGINS_OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated_code")
# For installed/nix layout, logos_sdk.cpp is already in ${PLUGINS_OUTPUT_DIR}
# (generated by nix build preConfigure phase in lib.nix before CMake runs)
list(APPEND SOURCES ${PLUGINS_OUTPUT_DIR}/logos_sdk.cpp)
endif()
# Create the plugin library
add_library(storage_ui SHARED ${SOURCES})
# Set output name without lib prefix and with correct name for generator
set_target_properties(storage_ui PROPERTIES
PREFIX ""
OUTPUT_NAME "storage_ui"
)
# Ensure generator runs before building the plugin (only for source layout)
if(_cpp_sdk_is_source)
add_dependencies(storage_ui run_cpp_generator_storage_ui)
endif()
# Include directories
target_include_directories(storage_ui PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${PLUGINS_OUTPUT_DIR}
)
# Add include directories based on layout type
if(_liblogos_is_source)
target_include_directories(storage_ui PRIVATE ${LOGOS_LIBLOGOS_ROOT})
else()
target_include_directories(storage_ui PRIVATE ${LOGOS_LIBLOGOS_ROOT}/include)
endif()
if(_cpp_sdk_is_source)
target_include_directories(storage_ui PRIVATE
${LOGOS_CPP_SDK_ROOT}/cpp
${LOGOS_CPP_SDK_ROOT}/cpp/generated
)
else()
# For nix builds, also include the include subdirectory
# (lib.nix moves header files to ./generated_code/include/)
target_include_directories(storage_ui PRIVATE
${LOGOS_CPP_SDK_ROOT}/include
${LOGOS_CPP_SDK_ROOT}/include/cpp
${LOGOS_CPP_SDK_ROOT}/include/core
${PLUGINS_OUTPUT_DIR}/include
)
endif()
# Link against libraries
target_link_libraries(storage_ui PRIVATE
Qt6::Core
Qt6::Widgets
Qt6::RemoteObjects
component-interfaces
)
# Link SDK library if using installed layout
if(NOT _cpp_sdk_is_source)
find_library(LOGOS_SDK_LIB logos_sdk PATHS ${LOGOS_CPP_SDK_ROOT}/lib NO_DEFAULT_PATH REQUIRED)
target_link_libraries(storage_ui PRIVATE ${LOGOS_SDK_LIB})
endif()
# Link against Abseil libraries if found
find_package(absl QUIET)
if(absl_FOUND)
target_link_libraries(storage_ui PRIVATE
absl::base
absl::strings
absl::log
absl::check
)
endif()
# Set common properties for both platforms
set_target_properties(storage_ui PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules" # For Windows .dll
BUILD_WITH_INSTALL_RPATH TRUE
SKIP_BUILD_RPATH FALSE)
if(APPLE)
# macOS specific settings
set_target_properties(storage_ui PROPERTIES
INSTALL_RPATH "@loader_path"
INSTALL_NAME_DIR "@rpath"
BUILD_WITH_INSTALL_NAME_DIR TRUE)
add_custom_command(TARGET storage_ui POST_BUILD
COMMAND install_name_tool -id "@rpath/storage_ui.dylib" $<TARGET_FILE:storage_ui>
COMMENT "Updating library paths for macOS"
)
else()
# Linux specific settings
set_target_properties(storage_ui PROPERTIES
INSTALL_RPATH "$ORIGIN"
INSTALL_RPATH_USE_LINK_PATH FALSE)
endif()
install(TARGETS storage_ui
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
)
install(FILES ${METADATA_JSON}
DESTINATION ${CMAKE_INSTALL_DATADIR}/logos-storage-ui
)
install(DIRECTORY "${PLUGINS_OUTPUT_DIR}/"
DESTINATION ${CMAKE_INSTALL_DATADIR}/logos-storage-ui/generated
OPTIONAL
)
# Print status messages
message(STATUS "Storage UI Plugin configured successfully")

11
StorageUIComponent.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "StorageUIComponent.h"
#include "src/StorageWidget.h"
QWidget* StorageUIComponent::createWidget(LogosAPI* logosAPI) {
// LogosAPI parameter available but not used - StorageWidget creates its own
return new StorageWidget();
}
void StorageUIComponent::destroyWidget(QWidget* widget) {
delete widget;
}

14
StorageUIComponent.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <IComponent.h>
#include <QObject>
class StorageUIComponent : public QObject, public IComponent {
Q_OBJECT
Q_INTERFACES(IComponent)
Q_PLUGIN_METADATA(IID IComponent_iid FILE "metadata.json")
public:
Q_INVOKABLE QWidget* createWidget(LogosAPI* logosAPI = nullptr) override;
void destroyWidget(QWidget* widget) override;
};

84
app/CMakeLists.txt Normal file
View File

@ -0,0 +1,84 @@
cmake_minimum_required(VERSION 3.16)
project(LogosStorageUIApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Find Qt packages
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets)
# Find logos-liblogos
if(NOT DEFINED LOGOS_LIBLOGOS_ROOT)
message(FATAL_ERROR "LOGOS_LIBLOGOS_ROOT must be defined")
endif()
# Find logos-cpp-sdk
if(NOT DEFINED LOGOS_CPP_SDK_ROOT)
message(FATAL_ERROR "LOGOS_CPP_SDK_ROOT must be defined")
endif()
message(STATUS "Using logos-liblogos at: ${LOGOS_LIBLOGOS_ROOT}")
message(STATUS "Using logos-cpp-sdk at: ${LOGOS_CPP_SDK_ROOT}")
# Check if logos_sdk library exists
if(NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.a" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.dylib" AND NOT EXISTS "${LOGOS_CPP_SDK_ROOT}/lib/liblogos_sdk.so")
message(WARNING "logos_sdk library not found in ${LOGOS_CPP_SDK_ROOT}/lib/")
message(STATUS "Available files in ${LOGOS_CPP_SDK_ROOT}/lib/:")
file(GLOB SDK_LIB_FILES "${LOGOS_CPP_SDK_ROOT}/lib/*")
foreach(file ${SDK_LIB_FILES})
message(STATUS " ${file}")
endforeach()
endif()
# Include directories - the new structure has headers in /include with subdirectories
include_directories(
${LOGOS_LIBLOGOS_ROOT}/include
${LOGOS_CPP_SDK_ROOT}/include
${LOGOS_CPP_SDK_ROOT}/include/cpp
${LOGOS_CPP_SDK_ROOT}/include/core
)
# Link directories
link_directories(
${LOGOS_LIBLOGOS_ROOT}/lib
${LOGOS_CPP_SDK_ROOT}/lib
)
# Set output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Create the executable
add_executable(logos-storage-ui-app
main.cpp
mainwindow.cpp
mainwindow.h
)
# Link libraries
target_link_libraries(logos-storage-ui-app PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
logos_core
logos_sdk
)
# Set RPATH settings for the executable
if(APPLE)
set_target_properties(logos-storage-ui-app PROPERTIES
INSTALL_RPATH "@executable_path/../lib"
BUILD_WITH_INSTALL_RPATH TRUE
)
elseif(UNIX)
set_target_properties(logos-storage-ui-app PROPERTIES
INSTALL_RPATH "$ORIGIN/../lib"
BUILD_WITH_INSTALL_RPATH TRUE
)
endif()
# Install rules
install(TARGETS logos-storage-ui-app
RUNTIME DESTINATION bin
)

90
app/main.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "mainwindow.h"
#include <QApplication>
#include <QDir>
#include <QDebug>
#include <iostream>
#include <memory>
// Replace CoreManager with direct C API functions
extern "C" {
void logos_core_set_plugins_dir(const char* plugins_dir);
void logos_core_start();
void logos_core_cleanup();
char** logos_core_get_loaded_plugins();
int logos_core_load_plugin(const char* plugin_name);
}
// Helper function to convert C-style array to QStringList
QStringList convertPluginsToStringList(char** plugins) {
QStringList result;
if (plugins) {
for (int i = 0; plugins[i] != nullptr; i++) {
result.append(plugins[i]);
}
}
return result;
}
int main(int argc, char *argv[])
{
// Create QApplication first
QApplication app(argc, argv);
// Set the plugins directory
QString pluginsDir = QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../modules");
std::cout << "Setting plugins directory to: " << pluginsDir.toStdString() << std::endl;
logos_core_set_plugins_dir(pluginsDir.toUtf8().constData());
// Start the core
logos_core_start();
std::cout << "Logos Core started successfully!" << std::endl;
// Explicitly load plugins in specified order
std::cout << "Loading plugins in specified order..." << std::endl;
// Load capability_module plugin first
if (logos_core_load_plugin("capability_module")) {
std::cout << "Successfully loaded capability_module plugin" << std::endl;
} else {
std::cerr << "Failed to load capability_module plugin" << std::endl;
}
// Load storage_module plugin second
if (logos_core_load_plugin("storage_module")) {
std::cout << "Successfully loaded storage_module plugin" << std::endl;
} else {
std::cerr << "Failed to load storage_module plugin" << std::endl;
}
// Print all loaded plugins
char** loadedPlugins = logos_core_get_loaded_plugins();
QStringList plugins = convertPluginsToStringList(loadedPlugins);
if (plugins.isEmpty()) {
qInfo() << "No plugins loaded.";
} else {
qInfo() << "Currently loaded plugins:";
for (const QString &plugin : plugins) {
qInfo() << " -" << plugin;
}
qInfo() << "Total plugins:" << plugins.size();
}
// Create and show the main window
MainWindow window;
window.show();
// Run the application
int result = app.exec();
qDebug() << "Application cleanup...";
window.cleanup();
// Cleanup core before exit
logos_core_cleanup();
return result;
}

113
app/mainwindow.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "mainwindow.h"
#include <QApplication>
#include <QCoreApplication>
#include <QPluginLoader>
#include <QDebug>
#include <QLabel>
#include <QVBoxLayout>
#include <QDir>
#include <QCloseEvent>
extern "C" {
void logos_core_cleanup();
}
void MainWindow::cleanup()
{
qDebug() << "MainWindow: Cleaning up before exit...";
if (storageWidget) {
bool running = false;
if (storageWidget) {
QMetaObject::invokeMethod(storageWidget, "isStorageRunning",
Qt::DirectConnection,
Q_RETURN_ARG(bool, running));
}
if (running) {
qDebug() << "MainWindow: Stopping Storage before destroying...";
QEventLoop loop;
QObject::connect(storageWidget, SIGNAL(storageStop()), &loop, SLOT(quit()));
QMetaObject::invokeMethod(storageWidget, "stopStorage", Qt::QueuedConnection);
loop.exec();
qDebug() << "MainWindow: Storage stopped.";
}
qDebug() << "MainWindow: Destroying Storage...";
QEventLoop loop;
QObject::connect(storageWidget, SIGNAL(storageCleanup()), &loop, SLOT(quit()));
QMetaObject::invokeMethod(storageWidget, "destroy", Qt::QueuedConnection);
loop.exec();
qDebug() << "MainWindow: Storage destroyed.";
}
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupUi();
}
MainWindow::~MainWindow()
{
}
void MainWindow::setupUi()
{
// Determine the appropriate plugin extension based on the platform
QString pluginExtension;
#if defined(Q_OS_WIN)
pluginExtension = ".dll";
#elif defined(Q_OS_MAC)
pluginExtension = ".dylib";
#else // Linux and other Unix-like systems
pluginExtension = ".so";
#endif
// Load the storage_ui plugin with the appropriate extension
QString pluginPath = QCoreApplication::applicationDirPath() + "/../storage_ui" + pluginExtension;
QPluginLoader loader(pluginPath);
QWidget* widget = nullptr;
if (loader.load()) {
QObject* plugin = loader.instance();
if (plugin) {
// Try to create the storage widget using the plugin's createWidget method
QMetaObject::invokeMethod(plugin, "createWidget",
Qt::DirectConnection,
Q_RETURN_ARG(QWidget*, widget));
}
}
if (widget) {
storageWidget = widget;
setCentralWidget(storageWidget);
} else {
qWarning() << "================================================";
qWarning() << "Failed to load storage UI plugin from:" << pluginPath;
qWarning() << "Error:" << loader.errorString();
qWarning() << "================================================";
// Fallback: show a message when plugin is not found
QWidget* fallbackWidget = new QWidget(this);
QVBoxLayout* layout = new QVBoxLayout(fallbackWidget);
QLabel* messageLabel = new QLabel("Storage UI module not loaded", fallbackWidget);
QFont font = messageLabel->font();
font.setPointSize(14);
messageLabel->setFont(font);
messageLabel->setAlignment(Qt::AlignCenter);
layout->addWidget(messageLabel);
setCentralWidget(fallbackWidget);
}
// Set window title and size
setWindowTitle("Logos Storage UI App");
// resize(800, 600);
}

24
app/mainwindow.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QCloseEvent;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void cleanup();
private:
void setupUi();
private:
QWidget *storageWidget = nullptr;
};
#endif // MAINWINDOW_H

View File

@ -1,5 +1,5 @@
{
description = "Logos Storage UI - A Qt UI app for Logos Storage";
description = "Logos Storage UI - A Qt UI plugin for Logos Storage";
inputs = {
# Follow the same nixpkgs as logos-liblogos to ensure compatibility
@ -30,6 +30,11 @@
};
src = ./.;
# Library package
lib = import ./nix/lib.nix {
inherit pkgs common src logosStorageModule logosSdk;
};
# App package
app = import ./nix/app.nix {
inherit pkgs common src logosLiblogos logosSdk logosStorageModule logosCapabilityModule;
@ -38,6 +43,7 @@
in
{
# Individual outputs
logos-storage-ui-lib = lib;
app = app;
# Default package

17
interfaces/IComponent.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <QObject>
#include <QWidget>
#include <QtPlugin>
class LogosAPI;
class IComponent {
public:
virtual ~IComponent() = default;
virtual QWidget* createWidget(LogosAPI* logosAPI = nullptr) = 0;
virtual void destroyWidget(QWidget* widget) = 0;
};
#define IComponent_iid "com.logos.component.IComponent"
Q_DECLARE_INTERFACE(IComponent, IComponent_iid)

290
src/StorageWidget.cpp Normal file
View File

@ -0,0 +1,290 @@
#include "StorageWidget.h"
#include <QDebug>
#include <QDateTime>
#include <QMessageBox>
#include <iostream>
#include <csignal>
#include <QTimer>
#include "logos_api_client.h"
int RET_OK = 0;
// Static pointer to the active StorageWidget for callbacks
static StorageWidget *activeWidget = nullptr;
StorageWidget::StorageWidget(QWidget *parent)
: QWidget(parent),
isStorageInitialized(false),
m_isStorageRunning(false),
m_logosAPI(nullptr)
{
// Set as the active widget
activeWidget = this;
m_logosAPI = new LogosAPI("core", this);
logos = new LogosModules(m_logosAPI);
// Main vertical layout
mainLayout = new QVBoxLayout(this);
// Create status label
statusLayout = new QHBoxLayout();
statusLabel = new QLabel("Status: Not initialized", this);
statusLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusLabel->setLineWidth(1);
statusLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
statusLabel->setMinimumHeight(30);
startButton = new QPushButton("Start", this);
statusLayout->addWidget(statusLabel, 4);
statusLayout->addWidget(startButton, 1);
// Create display
// storageDisplay = new QTextEdit(this);
// storageDisplay->setReadOnly(true);
// storageDisplay->setMinimumHeight(300);
// Create input layout
// inputLayout = new QHBoxLayout();
// messageInput = new QLineEdit(this);
// messageInput->setPlaceholderText("Type your message here...");
// sendButton = new QPushButton("Send", this);
// inputLayout->addWidget(messageInput, 4);
// inputLayout->addWidget(sendButton, 1);
// Add all components to main layout
mainLayout->addLayout(statusLayout);
// mainLayout->addWidget(storageDisplay);
// mainLayout->addLayout(inputLayout);
// Set spacing and margins
mainLayout->setSpacing(10);
mainLayout->setContentsMargins(20, 20, 20, 20);
// Connect signals to slots
connect(startButton, &QPushButton::clicked, this, &StorageWidget::onStartButtonClicked);
// connect(messageInput, &QLineEdit::returnPressed, this, &StorageWidget::onStartButtonClicked);
// Disable UI components until Storage is initialized
// messageInput->setEnabled(false);
// sendButton->setEnabled(false);
startButton->setEnabled(false);
// Auto-initialize Storage
initStorage();
}
StorageWidget::~StorageWidget()
{
// Reset the active widget if it's this instance
if (activeWidget == this)
{
activeWidget = nullptr;
}
}
void StorageWidget::initStorage()
{
updateStatus("Initializing Storage...");
response = logos->storage_module.init("{}");
qDebug() << "StorageWidget: Storage module init response:" << response;
isStorageInitialized = true;
m_isStorageRunning = false;
updateStatus("Storage initialized.");
if (!logos->storage_module.on("storageStart", [this](const QVariantList& data) {
int code = data[0].toInt();
if (code != RET_OK) {
updateStatus("Error starting Storage.");
} else {
updateStatus("Storage started successfully.");
m_isStorageRunning = true;
startButton->setText("Stop");
// messageInput->setEnabled(true);
// sendButton->setEnabled(true);
}
startButton->setEnabled(true);
})) {
qWarning() << "StorageWidget: failed to subscribe to storageStart events";
}
if (!logos->storage_module.on("storageStop", [this](const QVariantList& data) {
int code = data[0].toInt();
if (code != RET_OK) {
updateStatus("Error stopping Storage.");
} else {
updateStatus("Storage stopped successfully.");
m_isStorageRunning = false;
startButton->setText("Start");
// messageInput->setEnabled(false);
// sendButton->setEnabled(false);
}
startButton->setEnabled(true);
emit storageStop();
})) {
qWarning() << "StorageWidget: failed to subscribe to storageStop events";
}
startStorage();
// if (!storageModule.on("storageVersion", [this]
// std::string version = data[1].toString().toStdString();(const QVariantList& data) {
// qDebug() << "Storage Version:" << QString::fromStdString(version);
// })) {
// qWarning() << "ChatWidget: failed to subscribe to historyMessage events";
// }
// if (!storageModule.on("storageVersion", [this]
// std::string version = data[1].toString().toStdString();(const QVariantList& data) {
// qDebug() << "Storage Version:" << QString::fromStdString(version);
// })) {
// qWarning() << "ChatWidget: failed to subscribe to historyMessage events";
// }
}
bool StorageWidget::isStorageRunning() const
{
return m_isStorageRunning;
}
void StorageWidget::startStorage()
{
updateStatus("Starting Storage...");
if (!isStorageInitialized)
{
qDebug() << "StorageWidget: Storage not initialized, nothing to start.";
return;
}
if (m_isStorageRunning)
{
qDebug() << "StorageWidget: Storage already started.";
return;
}
if (!logos->storage_module.start()) {
qWarning() << "StorageWidget: Failed to send start command to Storage.";
} else {
qDebug() << "StorageWidget: Start command sent to Storage.";
}
}
void StorageWidget::stopStorage()
{
updateStatus("Stopping Storage...");
if (!isStorageInitialized)
{
qDebug() << "StorageWidget: Storage not initialized, nothing to stop.";
emit storageStop();
return;
}
if (!m_isStorageRunning)
{
qDebug() << "StorageWidget: Storage already stopped.";
emit storageStop();
return;
}
if (!logos->storage_module.stop()) {
qWarning() << "StorageWidget: Failed to send stop command to Storage.";
} else {
qDebug() << "StorageWidget: Stop command sent to Storage.";
}
}
void StorageWidget::destroy()
{
qDebug() << "StorageWidget: destroy function called...";
if (!isStorageInitialized)
{
qDebug() << "StorageWidget: Storage not initialized, nothing to stop.";
return;
}
if (!logos->storage_module.destroy()) {
qWarning() << "StorageWidget: Failed to send destroy command to Storage.";
} else {
qDebug() << "StorageWidget: Destroy command sent to Storage.";
}
qDebug() << "StorageWidget: Emitting storageCleanup signal.";
emit storageCleanup();
}
void StorageWidget::onStartButtonClicked()
{
qDebug() << "Starting Storage from button";
startButton->setEnabled(false);
if (m_isStorageRunning)
{
stopStorage();
}
else
{
startStorage();
}
}
void StorageWidget::onSendButtonClicked()
{
QString message = messageInput->text().trimmed();
if (message.isEmpty())
{
QMessageBox::warning(this, "Storage Error", "Message is empty.");
return;
}
// Check if Storage is running
if (!m_isStorageRunning)
{
QMessageBox::warning(this, "Storage Error", "Storage is not running. Please initialize Storage first.");
return;
}
logos->storage_module.version();
// if (m_logosAPI && m_logosAPI->getClient("storage")->isConnected())
// {
// logos->storage_module.storageVersion();
// }
// else
// {
// qDebug() << "LogosAPI not connected";
// }
qDebug() << "LogosAPI not connected!!";
// Clear input field
messageInput->clear();
}
void StorageWidget::updateStatus(const QString &message)
{
statusLabel->setText(message);
qDebug() << "StorageWidget Status:" << message;
}
void StorageWidget::displayMessage(const QString &sender, const QString &message)
{
QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
QString formattedMessage = QString("[%1] %2: %3").arg(timestamp, sender, message);
storageDisplay->append(formattedMessage);
}

69
src/StorageWidget.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QLineEdit>
#include <QLabel>
#include <string>
#include "logos_api.h"
#include "logos_api_client.h"
#include "logos_sdk.h"
using StringCallback = std::function<void(int, const std::string&)>;
class StorageWidget : public QWidget
{
Q_OBJECT
public:
explicit StorageWidget(QWidget *parent = nullptr);
~StorageWidget();
// Storage operations
Q_INVOKABLE void initStorage();
Q_INVOKABLE void startStorage();
Q_INVOKABLE void stopStorage();
Q_INVOKABLE void destroy();
Q_INVOKABLE bool isStorageRunning() const;
private slots:
void onSendButtonClicked();
void onStartButtonClicked();
private:
// UI elements
QVBoxLayout *mainLayout;
QHBoxLayout *inputLayout;
QHBoxLayout *statusLayout;
QHBoxLayout *channelLayout;
QTextEdit *storageDisplay;
QLineEdit *messageInput;
QLineEdit *channelInput;
QPushButton *sendButton;
QPushButton *startButton;
QLabel *statusLabel;
// LogosAPI instance for remote method calls
LogosAPI *m_logosAPI;
LogosModules *logos;
// Connection status
bool isStorageInitialized;
bool m_isStorageRunning;
QString currentPubSubTopic;
QString currentChannel;
bool response;
// Helper methods
void updateStatus(const QString &message);
void displayMessage(const QString &sender, const QString &message);
void emitEvent(const QString& eventName, const QVariantList& data);
signals:
void storageCleanup();
void storageStop();
};

76
src/StorageWindow.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "StorageWindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include <QDebug>
StorageWindow::StorageWindow(QWidget *parent) : QMainWindow(parent)
{
// Create central widget
storageWidget = new StorageWidget(this);
setCentralWidget(storageWidget);
// Setup the UI
setupMenu();
setupStatusBar();
// Set window properties
setMinimumSize(640, 480);
}
StorageWindow::~StorageWindow()
{
// StorageWidget will be deleted automatically as it's a child of this window
}
void StorageWindow::setupMenu()
{
// Create main menu
QMenu *fileMenu = menuBar()->addMenu("&File");
QMenu *storageMenu = menuBar()->addMenu("&Storage");
QMenu *helpMenu = menuBar()->addMenu("&Help");
// File menu actions
QAction *exitAction = fileMenu->addAction("E&xit");
connect(exitAction, &QAction::triggered, this, &QMainWindow::close);
// Storage menu actions
QAction *initStorageAction = storageMenu->addAction("&Initialize Storage");
connect(initStorageAction, &QAction::triggered, this, &StorageWindow::onInitStorage);
QAction *stopStorageAction = storageMenu->addAction("&Stop Storage");
connect(stopStorageAction, &QAction::triggered, this, &StorageWindow::onStopStorage);
// Help menu actions
QAction *aboutAction = helpMenu->addAction("&About");
connect(aboutAction, &QAction::triggered, this, &StorageWindow::onAboutAction);
}
void StorageWindow::setupStatusBar()
{
statusBar = new QStatusBar(this);
setStatusBar(statusBar);
statusBar->showMessage("Ready");
}
void StorageWindow::onAboutAction()
{
QMessageBox::about(this, "About Logos Storage",
"Logos Storage Application\n\n"
"A sample Qt application demonstrating Storage integration.");
}
void StorageWindow::onInitStorage()
{
qDebug() << "Initializing Storage from menu";
storageWidget->initStorage();
statusBar->showMessage("Storage initialization requested");
}
void StorageWindow::onStopStorage()
{
qDebug() << "Stopping Storage from menu";
storageWidget->stopStorage();
statusBar->showMessage("Storage stop requested");
}

27
src/StorageWindow.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include <QMainWindow>
#include <QVBoxLayout>
#include <QMenuBar>
#include <QStatusBar>
#include "StorageWidget.h"
class StorageWindow : public QMainWindow {
Q_OBJECT
public:
explicit StorageWindow(QWidget* parent = nullptr);
~StorageWindow();
private slots:
void onAboutAction();
void onInitStorage();
void onStopStorage();
private:
void setupMenu();
void setupStatusBar();
StorageWidget* storageWidget;
QStatusBar* statusBar;
};

17
src/main.cpp Normal file
View File

@ -0,0 +1,17 @@
#include <QApplication>
#include <QDebug>
#include "StorageWindow.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
qDebug() << "Starting Storage Qt Application";
// Create and show the main window
StorageWindow mainWindow;
mainWindow.setWindowTitle("Logos Storage App");
mainWindow.resize(800, 600);
mainWindow.show();
return app.exec();
}