diff --git a/vendor/DOtherSide/lib/CMakeLists.txt b/vendor/DOtherSide/lib/CMakeLists.txt index 521a134b2c..5c71255370 100644 --- a/vendor/DOtherSide/lib/CMakeLists.txt +++ b/vendor/DOtherSide/lib/CMakeLists.txt @@ -2,18 +2,28 @@ project(DOtherSide) include(GNUInstallDirs) +option(MONITORING "Tools for real-time inspection of the application." OFF) +set(MONITORING_QML_ENTRY_POINT "" CACHE STRING "QML file intended to start the monitoring tool UI.") + # Macro for merging common code between static and shared macro(add_target name type) find_package(Qt5 COMPONENTS Core Qml Gui Quick QuickControls2 Widgets Network Multimedia REQUIRED) - file(GLOB_RECURSE HEADERS include/DOtherSide/*.h) - if(APPLE) - file(GLOB_RECURSE SOURCES src/*.cpp src/*.mm) - else() - file(GLOB_RECURSE SOURCES src/*.cpp) + file(GLOB HEADERS include/DOtherSide/*.h include/DOtherSide/Status/*.h) + + file(GLOB SOURCES src/*.cpp src/Status/*.cpp) + + if(MONITORING) + file(GLOB MONITORING_HEADERS include/DOtherSide/Status/Monitoring/*.h) + file(GLOB MONITORING_SOURCES src/Status/Monitoring/*.cpp) endif() - add_library(${name} ${type} ${SOURCES} ${HEADERS}) + if(APPLE) + file(GLOB MM_FILES src/*.mm src/Status/*.mm) + list(APPEND SOURCES ${MM_FILES}) + endif() + + add_library(${name} ${type} ${SOURCES} ${HEADERS} ${MONITORING_SOURCES} ${MONITORING_HEADERS}) if (WIN32) target_compile_definitions(${name} PRIVATE -DWIN32) @@ -30,6 +40,11 @@ macro(add_target name type) target_compile_definitions(${name} PRIVATE QML_DEBUG_PORT=${QML_DEBUG_PORT}) endif() + if(MONITORING) + target_compile_definitions(${name} PRIVATE MONITORING) + target_compile_definitions(${name} PRIVATE MONITORING_QML_ENTRY_POINT="${MONITORING_QML_ENTRY_POINT}") + endif() + # for DOtherSide.pc set(PC_REQUIRES "Qt5Core, Qt5Gui, Qt5Widgets, Qt5Qml, Qt5Quick, Qt5Network, Qt5DBus, Qt5Multimedia, SortFilterProxyModel") if (${Qt5QuickControls2_FOUND}) diff --git a/vendor/DOtherSide/lib/include/DOtherSide/Status/Monitoring/Monitor.h b/vendor/DOtherSide/lib/include/DOtherSide/Status/Monitoring/Monitor.h new file mode 100644 index 0000000000..1a05ed63fa --- /dev/null +++ b/vendor/DOtherSide/lib/include/DOtherSide/Status/Monitoring/Monitor.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +class QQmlApplicationEngine; +class QQmlEngine; +class QJSEngine; + +class Monitor : public QObject +{ + Q_OBJECT + Q_PROPERTY(QStringList contexPropertiesNames READ getContextPropertiesNames + NOTIFY contextPropertiesNamesChanged) + + Monitor() = default; + +public: + void initialize(QQmlApplicationEngine *engine); + QStringList getContextPropertiesNames() const; + void addContextPropertyName(const QString &contextPropertyName); + + static Monitor& instance(); + static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine); +signals: + void contextPropertiesNamesChanged(); + +private: + QStringList m_contexPropertiesNames; +}; diff --git a/vendor/DOtherSide/lib/src/DOtherSide.cpp b/vendor/DOtherSide/lib/src/DOtherSide.cpp index a4fe879128..a3ec764c65 100644 --- a/vendor/DOtherSide/lib/src/DOtherSide.cpp +++ b/vendor/DOtherSide/lib/src/DOtherSide.cpp @@ -76,6 +76,11 @@ #include "DOtherSide/Status/QClipboardProxy.h" #include "DOtherSide/Status/RXValidator.h" +#ifdef MONITORING +#include +#include "DOtherSide/Status/Monitoring/Monitor.h" +#endif + #include namespace { @@ -87,6 +92,11 @@ void register_meta_types() qmlRegisterType("DotherSide", 0 , 1, "StatusSyntaxHighlighter"); qmlRegisterSingletonType("DotherSide", 0 , 1, "QClipboardProxy", &QClipboardProxy::qmlInstance); qmlRegisterType("DotherSide", 0, 1, "RXValidator"); + +#ifdef MONITORING + qmlRegisterSingletonType("Monitoring", 1 , 0, "Monitor", &Monitor::qmlInstance); +#endif + qqsfpm::registerTypes(); } @@ -342,7 +352,18 @@ void dos_qguiapplication_installEventFilter(::DosEvent* vptr) ::DosQQmlApplicationEngine *dos_qqmlapplicationengine_create() { +#ifdef MONITORING + auto engine = new QQmlApplicationEngine(); + auto disabledValue = QStringLiteral("0"); + + if (QProcessEnvironment::systemEnvironment().value( + QStringLiteral("DISABLE_MONITORING_WINDOW"), disabledValue) == disabledValue) + Monitor::instance().initialize(engine); + + return engine; +#else return new QQmlApplicationEngine(); +#endif } ::DosQQmlNetworkAccessManagerFactory *dos_qqmlnetworkaccessmanagerfactory_create(const char* tmpPath) @@ -601,6 +622,10 @@ void dos_qqmlcontext_setcontextproperty(::DosQQmlContext *vptr, const char *name auto context = static_cast(vptr); auto variant = static_cast(value); context->setContextProperty(QString::fromUtf8(name), *variant); + +#ifdef MONITORING + Monitor::instance().addContextPropertyName(QString::fromUtf8(name)); +#endif } ::DosQVariant *dos_qvariant_create() diff --git a/vendor/DOtherSide/lib/src/Status/Monitoring/Monitor.cpp b/vendor/DOtherSide/lib/src/Status/Monitoring/Monitor.cpp new file mode 100644 index 0000000000..3d860c0ad0 --- /dev/null +++ b/vendor/DOtherSide/lib/src/Status/Monitoring/Monitor.cpp @@ -0,0 +1,60 @@ +#include "DOtherSide/Status/Monitoring/Monitor.h" + +#include +#include +#include +#include +#include + +void Monitor::initialize(QQmlApplicationEngine* engine) { + QObject::connect(engine, &QQmlApplicationEngine::objectCreated, this, + [engine](QObject *obj, const QUrl &objUrl) { + if (!obj) { + qWarning() << "Error while loading QML:" << objUrl << "." + << "Monitor initialization failed."; + return; + } + + QQuickWindow* window = qobject_cast(obj); + QQmlComponent cmp(engine, QCoreApplication::applicationDirPath() + + QStringLiteral(MONITORING_QML_ENTRY_POINT), window); + + cmp.create(qmlContext(window)); + + if (cmp.isError()) { + qWarning() << "Failed to instantiate monitoring utilities:"; + qWarning() << cmp.errors(); + } + }, Qt::QueuedConnection); +} + +QStringList Monitor::getContextPropertiesNames() const +{ + return m_contexPropertiesNames; +} + +void Monitor::addContextPropertyName(const QString &contextPropertyName) +{ + if (m_contexPropertiesNames.contains(contextPropertyName)) + return; + + m_contexPropertiesNames << contextPropertyName; + emit contextPropertiesNamesChanged(); +} + +Monitor& Monitor::instance() +{ + static Monitor monitor; + return monitor; +} + +QObject* Monitor::qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine); + Q_UNUSED(scriptEngine); + + auto& inst = instance(); + engine->setObjectOwnership(&inst, QQmlEngine::CppOwnership); + + return &inst; +}