Files
metabuilder/frontends/qt6/main.cpp
johndoe6345789 e6a2a50ae1 feat(qt6): visual workflow canvas with infinite pan/zoom, Bezier connections, 152-node palette
Replace list-based WorkflowEditor with spatial infinite canvas:
- NodeRegistry C++ class loads 152 node types from node-registry.json
- 5000x5000 Flickable canvas with grid, Scale transform zoom (0.25x-2x)
- Draggable nodes with group-colored headers, input/output ports
- Bezier connection drawing via Canvas 2D (n8n adjacency map format)
- Interactive port-to-port connection creation with drag preview
- Searchable/filterable node palette with group chips
- Properties panel with schema-driven parameter editing
- Full n8n-style JSON: nodes, connections, variables, meta, tags
- DBAL integration preserved with mock workflow fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 03:03:34 +00:00

69 lines
2.7 KiB
C++

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QUrl>
#include <QDir>
#include "src/PackageRegistry.h"
#include "src/ModPlayer.h"
#include "src/DBALClient.h"
#include "src/PackageLoader.h"
#include "src/NodeRegistry.h"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// Add shared QML component library path
// Resolves: import QmlComponents 1.0
const auto appDir = QCoreApplication::applicationDirPath();
// Qt6 resolves "import QmlComponents" by looking for a QmlComponents/ dir
// inside each import path. We symlink or reference the parent of qml/.
const QStringList qmlParentPaths = {
appDir + "/../../",
appDir + "/../../../",
appDir + "/../../../../",
QDir::cleanPath(QStringLiteral(SRCDIR) + "/../..")
};
for (const auto &path : qmlParentPaths) {
const QString candidate = QDir(path).absolutePath();
// Check if QmlComponents symlink or qml/ dir with qmldir exists
if (QDir(candidate + "/QmlComponents").exists()
|| QDir(candidate + "/qml").exists()) {
engine.addImportPath(candidate);
break;
}
}
PackageRegistry registry;
ModPlayer modPlayer;
DBALClient dbalClient;
PackageLoader packageLoader;
NodeRegistry nodeRegistry;
registry.loadPackage("frontpage");
packageLoader.setPackagesDir(QDir(QStringLiteral(SRCDIR) + QStringLiteral("/packages")).absolutePath());
packageLoader.scan();
packageLoader.setWatching(true);
// Load workflow node type registry
const QString registryPath = QDir::cleanPath(
QStringLiteral(SRCDIR) + QStringLiteral("/../../workflow/plugins/registry/node-registry.json"));
nodeRegistry.loadRegistry(registryPath);
engine.rootContext()->setContextProperty(QStringLiteral("PackageRegistry"), &registry);
engine.rootContext()->setContextProperty(QStringLiteral("ModPlayer"), &modPlayer);
engine.rootContext()->setContextProperty(QStringLiteral("DBALClient"), &dbalClient);
engine.rootContext()->setContextProperty(QStringLiteral("PackageLoader"), &packageLoader);
engine.rootContext()->setContextProperty(QStringLiteral("NodeRegistry"), &nodeRegistry);
const QUrl url(QStringLiteral("qrc:/qt/qml/DBALObservatory/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && objUrl == url)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}