mirror of
https://github.com/logos-blockchain/lez-explorer-ui.git
synced 2026-04-08 04:23:18 +00:00
feat: initial project structure
This commit is contained in:
parent
65a3a59cf7
commit
e005abeee2
89
CMakeLists.txt
Normal file
89
CMakeLists.txt
Normal file
@ -0,0 +1,89 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(LEZExplorerUIPlugin 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)
|
||||
|
||||
# Find Qt packages
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||
|
||||
# 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_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces)
|
||||
add_library(component-interfaces INTERFACE)
|
||||
target_include_directories(component-interfaces INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/interfaces)
|
||||
endif()
|
||||
|
||||
# Source files
|
||||
set(SOURCES
|
||||
src/ExplorerPlugin.cpp
|
||||
src/ExplorerPlugin.h
|
||||
src/ExplorerWidget.cpp
|
||||
src/ExplorerWidget.h
|
||||
)
|
||||
|
||||
# Create the plugin library
|
||||
add_library(lez_explorer_ui SHARED ${SOURCES})
|
||||
|
||||
# Set output name without lib prefix
|
||||
set_target_properties(lez_explorer_ui PROPERTIES
|
||||
PREFIX ""
|
||||
OUTPUT_NAME "lez_explorer_ui"
|
||||
)
|
||||
|
||||
# Include directories
|
||||
target_include_directories(lez_explorer_ui PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# Link against libraries
|
||||
target_link_libraries(lez_explorer_ui PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Widgets
|
||||
component-interfaces
|
||||
)
|
||||
|
||||
# Set common properties for both platforms
|
||||
set_target_properties(lez_explorer_ui PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
SKIP_BUILD_RPATH FALSE
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(lez_explorer_ui PROPERTIES
|
||||
INSTALL_RPATH "@loader_path"
|
||||
INSTALL_NAME_DIR "@rpath"
|
||||
BUILD_WITH_INSTALL_NAME_DIR TRUE
|
||||
)
|
||||
add_custom_command(TARGET lez_explorer_ui POST_BUILD
|
||||
COMMAND install_name_tool -id "@rpath/lez_explorer_ui.dylib" $<TARGET_FILE:lez_explorer_ui>
|
||||
COMMENT "Updating library paths for macOS"
|
||||
)
|
||||
else()
|
||||
set_target_properties(lez_explorer_ui PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN"
|
||||
INSTALL_RPATH_USE_LINK_PATH FALSE
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS lez_explorer_ui
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/logos/modules
|
||||
)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/metadata.json
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/lez-explorer-ui
|
||||
)
|
||||
|
||||
message(STATUS "LEZ Explorer UI Plugin configured successfully")
|
||||
44
app/CMakeLists.txt
Normal file
44
app/CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(LEZExplorerUIApp 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(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||
|
||||
# Set output directories
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# Create the executable
|
||||
add_executable(lez-explorer-ui-app
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(lez-explorer-ui-app PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
# Set RPATH settings for the executable
|
||||
if(APPLE)
|
||||
set_target_properties(lez-explorer-ui-app PROPERTIES
|
||||
INSTALL_RPATH "@executable_path/../lib"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
elseif(UNIX)
|
||||
set_target_properties(lez-explorer-ui-app PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN/../lib"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install rules
|
||||
install(TARGETS lez-explorer-ui-app
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
13
app/main.cpp
Normal file
13
app/main.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
MainWindow window;
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
60
app/mainwindow.cpp
Normal file
60
app/mainwindow.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
setupUi();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() = default;
|
||||
|
||||
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
|
||||
pluginExtension = ".so";
|
||||
#endif
|
||||
|
||||
QString pluginPath = QCoreApplication::applicationDirPath() + "/../lez_explorer_ui" + pluginExtension;
|
||||
QPluginLoader loader(pluginPath);
|
||||
|
||||
QWidget* explorerWidget = nullptr;
|
||||
|
||||
if (loader.load()) {
|
||||
QObject* plugin = loader.instance();
|
||||
if (plugin) {
|
||||
QMetaObject::invokeMethod(plugin, "createWidget",
|
||||
Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QWidget*, explorerWidget));
|
||||
}
|
||||
}
|
||||
|
||||
if (explorerWidget) {
|
||||
setCentralWidget(explorerWidget);
|
||||
} else {
|
||||
qWarning() << "Failed to load LEZ Explorer UI plugin from:" << pluginPath;
|
||||
qWarning() << "Error:" << loader.errorString();
|
||||
|
||||
auto* fallbackWidget = new QWidget(this);
|
||||
auto* layout = new QVBoxLayout(fallbackWidget);
|
||||
|
||||
auto* messageLabel = new QLabel("LEZ Explorer UI module not loaded", fallbackWidget);
|
||||
QFont font = messageLabel->font();
|
||||
font.setPointSize(14);
|
||||
messageLabel->setFont(font);
|
||||
messageLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
layout->addWidget(messageLabel);
|
||||
setCentralWidget(fallbackWidget);
|
||||
}
|
||||
|
||||
setWindowTitle("LEZ Explorer");
|
||||
resize(1024, 768);
|
||||
}
|
||||
14
app/mainwindow.h
Normal file
14
app/mainwindow.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = nullptr);
|
||||
~MainWindow() override;
|
||||
|
||||
private:
|
||||
void setupUi();
|
||||
};
|
||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1751274312,
|
||||
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
53
flake.nix
Normal file
53
flake.nix
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
description = "LEZ Explorer UI - A Qt block explorer for the Logos Execution Zone";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
systems = [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ];
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f {
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
});
|
||||
in
|
||||
{
|
||||
packages = forAllSystems ({ pkgs }:
|
||||
let
|
||||
common = import ./nix/default.nix { inherit pkgs; };
|
||||
src = ./.;
|
||||
|
||||
lib = import ./nix/lib.nix { inherit pkgs common src; };
|
||||
|
||||
app = import ./nix/app.nix {
|
||||
inherit pkgs common src;
|
||||
lezExplorerUI = lib;
|
||||
};
|
||||
in
|
||||
{
|
||||
lez-explorer-ui-lib = lib;
|
||||
app = app;
|
||||
lib = lib;
|
||||
default = lib;
|
||||
}
|
||||
);
|
||||
|
||||
devShells = forAllSystems ({ pkgs }: {
|
||||
default = pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.ninja
|
||||
pkgs.pkg-config
|
||||
];
|
||||
buildInputs = [
|
||||
pkgs.qt6.qtbase
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
echo "LEZ Explorer UI development environment"
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
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)
|
||||
10
metadata.json
Normal file
10
metadata.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "lez_explorer_ui",
|
||||
"version": "1.0.0",
|
||||
"description": "LEZ Explorer UI - A block explorer for the Logos Execution Zone",
|
||||
"type": "ui",
|
||||
"main": "lez_explorer_ui",
|
||||
"dependencies": [],
|
||||
"category": "explorer",
|
||||
"capabilities": ["ui_components"]
|
||||
}
|
||||
64
nix/app.nix
Normal file
64
nix/app.nix
Normal file
@ -0,0 +1,64 @@
|
||||
# Builds the lez-explorer-ui-app standalone application
|
||||
{ pkgs, common, src, lezExplorerUI }:
|
||||
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
pname = "lez-explorer-ui-app";
|
||||
version = common.version;
|
||||
|
||||
inherit src;
|
||||
inherit (common) buildInputs meta;
|
||||
|
||||
nativeBuildInputs = common.nativeBuildInputs ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.patchelf ];
|
||||
|
||||
# This is a GUI application, enable Qt wrapping
|
||||
dontWrapQtApps = false;
|
||||
|
||||
qtLibPath = pkgs.lib.makeLibraryPath ([
|
||||
pkgs.qt6.qtbase
|
||||
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
|
||||
pkgs.libglvnd
|
||||
]);
|
||||
|
||||
qtPluginPath = "${pkgs.qt6.qtbase}/lib/qt-6/plugins";
|
||||
|
||||
qtWrapperArgs = [
|
||||
"--prefix" "LD_LIBRARY_PATH" ":" qtLibPath
|
||||
"--prefix" "QT_PLUGIN_PATH" ":" qtPluginPath
|
||||
];
|
||||
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
cmake -S app -B build \
|
||||
-GNinja \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
cmake --build build
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/bin $out/lib
|
||||
|
||||
# Install the app binary
|
||||
cp build/bin/lez-explorer-ui-app $out/bin/
|
||||
|
||||
# Determine platform-specific plugin extension
|
||||
OS_EXT="so"
|
||||
case "$(uname -s)" in
|
||||
Darwin) OS_EXT="dylib";;
|
||||
esac
|
||||
|
||||
# Copy the explorer UI plugin to root directory (loaded relative to binary)
|
||||
if [ -f "${lezExplorerUI}/lib/lez_explorer_ui.$OS_EXT" ]; then
|
||||
cp -L "${lezExplorerUI}/lib/lez_explorer_ui.$OS_EXT" "$out/"
|
||||
fi
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
27
nix/default.nix
Normal file
27
nix/default.nix
Normal file
@ -0,0 +1,27 @@
|
||||
# Common build configuration shared across all packages
|
||||
{ pkgs }:
|
||||
|
||||
{
|
||||
pname = "lez-explorer-ui";
|
||||
version = "1.0.0";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.ninja
|
||||
pkgs.pkg-config
|
||||
pkgs.qt6.wrapQtAppsHook
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
pkgs.qt6.qtbase
|
||||
];
|
||||
|
||||
cmakeFlags = [
|
||||
"-GNinja"
|
||||
];
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
description = "LEZ Explorer UI - A Qt block explorer for the Logos Execution Zone";
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
}
|
||||
45
nix/lib.nix
Normal file
45
nix/lib.nix
Normal file
@ -0,0 +1,45 @@
|
||||
# Builds the lez-explorer-ui library (Qt plugin)
|
||||
{ pkgs, common, src }:
|
||||
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "${common.pname}-lib";
|
||||
version = common.version;
|
||||
|
||||
inherit src;
|
||||
inherit (common) buildInputs cmakeFlags meta;
|
||||
nativeBuildInputs = common.nativeBuildInputs;
|
||||
|
||||
# Library (Qt plugin), not an app — no Qt wrapper
|
||||
dontWrapQtApps = true;
|
||||
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
cmake -S . -B build \
|
||||
-GNinja \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
cmake --build build
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/lib
|
||||
if [ -f build/modules/lez_explorer_ui.dylib ]; then
|
||||
cp build/modules/lez_explorer_ui.dylib $out/lib/
|
||||
elif [ -f build/modules/lez_explorer_ui.so ]; then
|
||||
cp build/modules/lez_explorer_ui.so $out/lib/
|
||||
else
|
||||
echo "Error: No library file found in build/modules/"
|
||||
ls -la build/modules/ 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
17
src/ExplorerPlugin.cpp
Normal file
17
src/ExplorerPlugin.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "ExplorerPlugin.h"
|
||||
#include "ExplorerWidget.h"
|
||||
|
||||
ExplorerPlugin::ExplorerPlugin(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget* ExplorerPlugin::createWidget(LogosAPI* /*logosAPI*/)
|
||||
{
|
||||
return new ExplorerWidget();
|
||||
}
|
||||
|
||||
void ExplorerPlugin::destroyWidget(QWidget* widget)
|
||||
{
|
||||
delete widget;
|
||||
}
|
||||
18
src/ExplorerPlugin.h
Normal file
18
src/ExplorerPlugin.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "IComponent.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
|
||||
class ExplorerPlugin : public QObject, public IComponent {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(IComponent)
|
||||
Q_PLUGIN_METADATA(IID IComponent_iid FILE "metadata.json")
|
||||
|
||||
public:
|
||||
explicit ExplorerPlugin(QObject* parent = nullptr);
|
||||
|
||||
Q_INVOKABLE QWidget* createWidget(LogosAPI* logosAPI = nullptr) override;
|
||||
void destroyWidget(QWidget* widget) override;
|
||||
};
|
||||
38
src/ExplorerWidget.cpp
Normal file
38
src/ExplorerWidget.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "ExplorerWidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
ExplorerWidget::ExplorerWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
|
||||
auto* label = new QLabel("LEZ Explorer", this);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
QFont font = label->font();
|
||||
font.setPointSize(24);
|
||||
font.setBold(true);
|
||||
label->setFont(font);
|
||||
label->setStyleSheet("color: white;");
|
||||
|
||||
layout->addWidget(label);
|
||||
}
|
||||
|
||||
void ExplorerWidget::paintEvent(QPaintEvent* /*event*/)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Draw a blue rectangle filling the widget
|
||||
painter.setBrush(QColor(30, 60, 120));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRect(rect());
|
||||
|
||||
// Draw a lighter inner rectangle
|
||||
int margin = 40;
|
||||
QRect inner = rect().adjusted(margin, margin, -margin, -margin);
|
||||
painter.setBrush(QColor(40, 80, 160));
|
||||
painter.drawRoundedRect(inner, 16, 16);
|
||||
}
|
||||
13
src/ExplorerWidget.h
Normal file
13
src/ExplorerWidget.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ExplorerWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExplorerWidget(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user