diff --git a/.gitignore b/.gitignore index b46870cc3..69106b9df 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,7 @@ coverage_html_report/ **/rln_tree/ **/certs/ +# simple qt example +.qmake.stash +main-qt +waku_handler.moc.cpp diff --git a/examples/qt/Makefile b/examples/qt/Makefile new file mode 100644 index 000000000..aa2147edb --- /dev/null +++ b/examples/qt/Makefile @@ -0,0 +1,26 @@ + +## Has been compiled with Qt 5.15.2 + +## If change the main.qml, the qmake should be called +## This may be needed in Ubuntu: sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev + +CXX = g++ +CXXFLAGS = -g3 -fpermissive -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Qml Qt5Quick` +LDFLAGS = `pkg-config --libs Qt5Core Qt5Gui Qt5Qml Qt5Quick` -lwaku -L../../build/ +MOC = moc + +TARGET = main-qt +SRC = main_qt.cpp +MOC_SRC = waku_handler.moc.cpp +HEADERS = waku_handler.h + +all: $(TARGET) + +$(MOC_SRC): $(HEADERS) + $(MOC) $< -o $@ + +$(TARGET): $(SRC) $(MOC_SRC) + $(CXX) $(CXXFLAGS) -o $(TARGET) $(SRC) $(MOC_SRC) $(LDFLAGS) + +clean: + rm -f $(TARGET) $(MOC_SRC) diff --git a/examples/qt/main.qml b/examples/qt/main.qml new file mode 100644 index 000000000..7ef2dcc55 --- /dev/null +++ b/examples/qt/main.qml @@ -0,0 +1,64 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +ApplicationWindow { + visible: true + width: 400 + height: 300 + title: "Hello, World!" + + Column { + anchors.centerIn: parent + spacing: 20 + + Label { + text: "Hello, World!" + font.pixelSize: 24 + horizontalAlignment: Text.AlignHCenter + } + } + + Rectangle { + width: parent.width + height: 60 + anchors.bottom: parent.bottom + color: "transparent" + + Row { + anchors.centerIn: parent + spacing: 30 + + Button { + text: "Start Waku Node" + width: 150 + height: 40 + font.pixelSize: 16 + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: wakuHandler.start() + } + background: Rectangle { + color: "#2196F3" + radius: 10 + } + } + + Button { + text: "Stop Waku Node" + width: 150 + height: 40 + font.pixelSize: 16 + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: wakuHandler.stop() + } + background: Rectangle { + color: "#F44336" + radius: 10 + } + } + } + } +} diff --git a/examples/qt/main_qt.cpp b/examples/qt/main_qt.cpp new file mode 100644 index 000000000..f16660c17 --- /dev/null +++ b/examples/qt/main_qt.cpp @@ -0,0 +1,46 @@ +#include +#include +#include + +#include "waku_handler.h" + +void event_handler(int callerRet, const char* msg, size_t len, void* userData) { + printf("Receiving message %s\n", msg); +} + +int main(int argc, char *argv[]) { + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; + + WakuHandler wakuHandler; + void* userData = nullptr; + + QString jsonConfig = R"( + { + "tcpPort": 60000, + "relay": true, + "logLevel": "TRACE", + "discv5Discovery": true, + "discv5BootstrapNodes": [ + "enr:-QESuEB4Dchgjn7gfAvwB00CxTA-nGiyk-aALI-H4dYSZD3rUk7bZHmP8d2U6xDiQ2vZffpo45Jp7zKNdnwDUx6g4o6XAYJpZIJ2NIJpcIRA4VDAim11bHRpYWRkcnO4XAArNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwAtNiZub2RlLTAxLmRvLWFtczMud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQOvD3S3jUNICsrOILlmhENiWAMmMVlAl6-Q8wRB7hidY4N0Y3CCdl-DdWRwgiMohXdha3UyDw", + "enr:-QEkuEBIkb8q8_mrorHndoXH9t5N6ZfD-jehQCrYeoJDPHqT0l0wyaONa2-piRQsi3oVKAzDShDVeoQhy0uwN1xbZfPZAYJpZIJ2NIJpcIQiQlleim11bHRpYWRkcnO4bgA0Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS5zYW5kYm94LnN0YXR1cy5pbQZ2XwA2Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS5zYW5kYm94LnN0YXR1cy5pbQYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQKnGt-GSgqPSf3IAPM7bFgTlpczpMZZLF3geeoNNsxzSoN0Y3CCdl-DdWRwgiMohXdha3UyDw" + ], + "discv5UdpPort": 9999, + "dnsDiscovery": true, + "dnsDiscoveryUrl": "enrtree://AOGYWMBYOUIMOENHXCHILPKY3ZRFEULMFI4DOM442QSZ73TT2A7VI@test.waku.nodes.status.im", + "dnsDiscoveryNameServers": ["8.8.8.8", "1.0.0.1"] + } + )"; + + wakuHandler.initialize(jsonConfig, event_handler, userData); + + engine.rootContext()->setContextProperty("wakuHandler", &wakuHandler); + + engine.load(QUrl::fromLocalFile("main.qml")); + + if (engine.rootObjects().isEmpty()) + return -1; + + return app.exec(); +} + diff --git a/examples/qt/qt.pro b/examples/qt/qt.pro new file mode 100644 index 000000000..7e1770d8d --- /dev/null +++ b/examples/qt/qt.pro @@ -0,0 +1,18 @@ +###################################################################### +# Automatically generated by qmake (3.1) Thu Feb 27 21:42:11 2025 +###################################################################### + +TEMPLATE = app +TARGET = qt +INCLUDEPATH += . + +# You can make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# Please consult the documentation of the deprecated API in order to know +# how to port your code away from it. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +# Input +HEADERS += waku_handler.h +SOURCES += main_qt.cpp waku_hand.moc.cpp waku_handler.moc.cpp diff --git a/examples/qt/waku_handler.h b/examples/qt/waku_handler.h new file mode 100644 index 000000000..161a17c82 --- /dev/null +++ b/examples/qt/waku_handler.h @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "../../library/libwaku.h" + +class WakuHandler : public QObject { + Q_OBJECT +private: + static void event_handler(int callerRet, const char* msg, size_t len, void* userData) { + printf("Receiving message %s\n", msg); + } + + static void on_event_received(int callerRet, const char* msg, size_t len, void* userData) { + if (callerRet == RET_ERR) { + printf("Error: %s\n", msg); + exit(1); + } + else if (callerRet == RET_OK) { + printf("Receiving event: %s\n", msg); + } + } + +public: + WakuHandler() : QObject(), ctx(nullptr) {} + + void initialize(const QString& jsonConfig, WakuCallBack event_handler, void* userData) { + ctx = waku_new(jsonConfig.toUtf8().constData(), WakuCallBack(event_handler), userData); + + waku_set_event_callback(ctx, on_event_received, userData); + qDebug() << "Waku context initialized, ready to start."; + } + + Q_INVOKABLE void start() { + if (ctx) { + waku_start(ctx, event_handler, nullptr); + qDebug() << "Waku start called with event_handler and userData."; + } else { + qDebug() << "Context is not initialized in start."; + } + } + + Q_INVOKABLE void stop() { + if (ctx) { + waku_stop(ctx, event_handler, nullptr); + qDebug() << "Waku stop called with event_handler and userData."; + } else { + qDebug() << "Context is not initialized in stop."; + } + } + + virtual ~WakuHandler() {} + +private: + void* ctx; +};