mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-07-29 02:13:12 +00:00
Init app
This commit is contained in:
parent
ba4214d872
commit
067af5f944
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
result
|
||||
data/
|
||||
272
CMakeLists.txt
Normal file
272
CMakeLists.txt
Normal 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
11
StorageUIComponent.cpp
Normal 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
14
StorageUIComponent.h
Normal 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
84
app/CMakeLists.txt
Normal 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
90
app/main.cpp
Normal 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
113
app/mainwindow.cpp
Normal 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
24
app/mainwindow.h
Normal 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
|
||||
@ -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
17
interfaces/IComponent.h
Normal 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
290
src/StorageWidget.cpp
Normal 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
69
src/StorageWidget.h
Normal 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
76
src/StorageWindow.cpp
Normal 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
27
src/StorageWindow.h
Normal 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
17
src/main.cpp
Normal 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();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user