From e73fe498e86dbb20d74f8d6ca13b541642676b82 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Thu, 19 Feb 2026 18:00:52 +0100 Subject: Rename QML singleton to Bobink and simplify singleton lifecycle Replace QML_ELEMENT with QML_NAMED_ELEMENT(Bobink) so QML references use `Bobink` instead of `BobinkClient`. Remove instance()/create() factory in favor of inline s_instance set in the constructor. Import BobinkPlugin statically in demo, link demo to BobinkQtOpcUaplugin, and make library link dependencies PUBLIC. Add .qtcreator to gitignore. --- src/BobinkClient.cpp | 28 +++------------------------- src/BobinkClient.h | 13 +++++++------ src/BobinkNode.cpp | 30 +++++++++++++----------------- src/CMakeLists.txt | 3 ++- 4 files changed, 25 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/BobinkClient.cpp b/src/BobinkClient.cpp index f8303a3..01f9912 100644 --- a/src/BobinkClient.cpp +++ b/src/BobinkClient.cpp @@ -11,8 +11,6 @@ using namespace Qt::Literals::StringLiterals; -BobinkClient *BobinkClient::s_instance = nullptr; - static QString defaultPkiDir () { @@ -36,35 +34,15 @@ BobinkClient::BobinkClient (QObject *parent) : QObject (parent), m_provider (new QOpcUaProvider (this)), m_pkiDir (defaultPkiDir ()) { + // Singleton pattern: construct only once + Q_ASSERT(!s_instance); ensurePkiDirs (m_pkiDir); setupClient (); autoDetectPki (); applyPki (); connect (&m_discoveryTimer, &QTimer::timeout, this, &BobinkClient::doDiscovery); -} - -BobinkClient::~BobinkClient () -{ - if (s_instance == this) - s_instance = nullptr; -} - -BobinkClient * -BobinkClient::instance () -{ - return s_instance; -} - -BobinkClient * -BobinkClient::create (QQmlEngine *, QJSEngine *) -{ - if (!s_instance) - { - s_instance = new BobinkClient; - QJSEngine::setObjectOwnership (s_instance, QJSEngine::CppOwnership); - } - return s_instance; + s_instance = this; } void diff --git a/src/BobinkClient.h b/src/BobinkClient.h index 5b7b284..3f36e75 100644 --- a/src/BobinkClient.h +++ b/src/BobinkClient.h @@ -25,8 +25,8 @@ class BobinkAuth; class BobinkClient : public QObject { Q_OBJECT - QML_ELEMENT QML_SINGLETON + QML_NAMED_ELEMENT (Bobink) Q_PROPERTY (bool connected READ connected NOTIFY connectedChanged) Q_PROPERTY (QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY @@ -45,16 +45,18 @@ class BobinkClient : public QObject QString keyFile READ keyFile WRITE setKeyFile NOTIFY keyFileChanged) public: - explicit BobinkClient (QObject *parent = nullptr); - ~BobinkClient () override; + BobinkClient (QObject *parent = nullptr); + // ~BobinkClient () override; - static BobinkClient *instance (); + static inline BobinkClient *s_instance = nullptr; + + // static BobinkClient *instance (); /** * @brief QML singleton factory. * @note CppOwnership — lives for the process lifetime. */ - static BobinkClient *create (QQmlEngine *qmlEngine, QJSEngine *jsEngine); + // static BobinkClient *create (QQmlEngine *qmlEngine, QJSEngine *jsEngine); bool connected () const; @@ -155,7 +157,6 @@ private slots: private: void setupClient (); - static BobinkClient *s_instance; QOpcUaProvider *m_provider = nullptr; QOpcUaClient *m_client = nullptr; BobinkAuth *m_auth = nullptr; diff --git a/src/BobinkNode.cpp b/src/BobinkNode.cpp index a39c195..fed87bc 100644 --- a/src/BobinkNode.cpp +++ b/src/BobinkNode.cpp @@ -104,7 +104,7 @@ BobinkNode::componentComplete () QQuickItem::componentComplete (); m_componentComplete = true; - auto *client = BobinkClient::instance (); + auto *client = BobinkClient::s_instance; if (client) connect (client, &BobinkClient::connectedChanged, this, &BobinkNode::handleClientConnectedChanged); @@ -137,7 +137,7 @@ BobinkNode::startMonitoring () if (m_opcuaNode || m_nodeId.isEmpty ()) return; - auto *client = BobinkClient::instance (); + auto *client = BobinkClient::s_instance; if (!client || !client->connected ()) return; @@ -245,11 +245,10 @@ BobinkNode::handleAttributeWritten (QOpcUa::NodeAttribute attr, void BobinkNode::handleClientConnectedChanged () { - auto *client = BobinkClient::instance (); - if (!client) + if (!BobinkClient::s_instance) return; - if (client->connected ()) + if (BobinkClient::s_instance->connected ()) { if (m_componentComplete && isVisible ()) startMonitoring (); @@ -263,8 +262,7 @@ BobinkNode::handleClientConnectedChanged () void BobinkNode::handleAttributeReadFinished (QOpcUa::NodeAttributes attrs) { - auto *client = BobinkClient::instance (); - if (!client || !m_opcuaNode) + if (!BobinkClient::s_instance || !m_opcuaNode) return; for (int bit = 0; bit < 27; ++bit) @@ -276,12 +274,12 @@ BobinkNode::handleAttributeReadFinished (QOpcUa::NodeAttributes attrs) auto sc = m_opcuaNode->attributeError (attr); QLatin1StringView name = nameFromAttribute (attr); if (sc == QOpcUa::UaStatusCode::Good) - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Read %1.%2 = %3") .arg (m_nodeId, name, m_opcuaNode->attribute (attr).toString ())); else - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Read %1.%2 failed: 0x%3") .arg (m_nodeId, name) .arg (static_cast (sc), 8, 16, QLatin1Char ('0'))); @@ -292,15 +290,14 @@ void BobinkNode::handleEnableMonitoringFinished (QOpcUa::NodeAttribute, QOpcUa::UaStatusCode statusCode) { - auto *client = BobinkClient::instance (); - if (!client) + if (!BobinkClient::s_instance) return; if (statusCode == QOpcUa::Good) - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Monitoring started: %1").arg (m_nodeId)); else - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Monitoring failed for %1: 0x%2") .arg (m_nodeId) .arg (static_cast (statusCode), 8, 16, @@ -311,15 +308,14 @@ void BobinkNode::handleDisableMonitoringFinished (QOpcUa::NodeAttribute, QOpcUa::UaStatusCode statusCode) { - auto *client = BobinkClient::instance (); - if (!client) + if (!BobinkClient::s_instance) return; if (statusCode == QOpcUa::Good) - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Monitoring stopped: %1").arg (m_nodeId)); else - emit client->statusMessage ( + emit BobinkClient::s_instance->statusMessage ( QStringLiteral ("Stop monitoring failed for %1: 0x%2") .arg (m_nodeId) .arg (static_cast (statusCode), 8, 16, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5898132..1292194 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,4 @@ +qt_add_library(BobinkQtOpcUa STATIC) # BobinkQtOpcUa — QML module wrapping QtOpcUa for declarative use. qt_add_qml_module( BobinkQtOpcUa @@ -15,4 +16,4 @@ qt_add_qml_module( OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml/Bobink") -target_link_libraries(BobinkQtOpcUa PRIVATE Qt6::Core Qt6::Quick Qt6::OpcUa) +target_link_libraries(BobinkQtOpcUa PUBLIC Qt6::Core Qt6::Quick Qt6::OpcUa) -- cgit v1.2.3