From f75e4e0c47feae21c170ebd0e8ab0f029717dc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 11 Oct 2024 17:14:21 +0200 Subject: [PATCH] Introduce ability of calling StatusQ methods from nim Closes: #16496 --- Makefile | 17 ++- config.nims | 1 + scripts/fix_app_dir.sh | 2 +- scripts/init_app_dir.sh | 3 +- src/nim_status_client.nim | 4 + src/statusq_bridge.nim | 3 + storybook/CMakeLists.txt | 10 +- storybook/main.cpp | 6 +- storybook/qmlTests/main.cpp | 4 + storybook/validator_main.cpp | 4 +- ui/StatusQ/CMakeLists.txt | 37 +----- .../include/StatusQ/stringutilsinternal.h | 8 +- .../include/StatusQ/typesregistration.h | 3 + ui/StatusQ/sandbox/CMakeLists.txt | 2 +- .../sandbox/demoapp/ChatChannelView.qml | 1 - .../demoapp/StatusAppCommunityView.qml | 4 - ui/StatusQ/sandbox/sandboxapp.cpp | 6 +- ui/StatusQ/sanity_checker/CMakeLists.txt | 9 +- ui/StatusQ/sanity_checker/main.cpp | 15 +-- ui/StatusQ/src/StatusQ/qmldir | 3 - ui/StatusQ/src/externc.cpp | 11 ++ ui/StatusQ/src/plugin.cpp | 119 ------------------ ui/StatusQ/src/stringutilsinternal.cpp | 29 +++-- ui/StatusQ/src/typesregistration.cpp | 105 ++++++++++++++++ ui/StatusQ/tests/CMakeLists.txt | 1 - ui/StatusQ/tests/main.cpp | 4 + 26 files changed, 190 insertions(+), 221 deletions(-) create mode 100644 src/statusq_bridge.nim create mode 100644 ui/StatusQ/include/StatusQ/typesregistration.h delete mode 100644 ui/StatusQ/src/StatusQ/qmldir create mode 100644 ui/StatusQ/src/externc.cpp delete mode 100644 ui/StatusQ/src/plugin.cpp create mode 100644 ui/StatusQ/src/typesregistration.cpp diff --git a/Makefile b/Makefile index 8f94537279..76c00e897e 100644 --- a/Makefile +++ b/Makefile @@ -258,7 +258,7 @@ endif STATUSQ_SOURCE_PATH := ui/StatusQ STATUSQ_BUILD_PATH := ui/StatusQ/build -STATUSQ_INSTALL_PATH := $(shell pwd)/bin +export STATUSQ_INSTALL_PATH := $(shell pwd)/bin STATUSQ_CMAKE_CACHE := $(STATUSQ_BUILD_PATH)/CMakeCache.txt $(STATUSQ_CMAKE_CACHE): | check-qt-dir @@ -562,6 +562,8 @@ $(NIM_STATUS_CLIENT): $(NIM_SOURCES) | statusq dotherside check-qt-dir $(STATUSG $(ENV_SCRIPT) nim c $(NIM_PARAMS) \ --passL:"-L$(STATUSGO_LIBDIR)" \ --passL:"-lstatus" \ + --passL:"-L$(STATUSQ_INSTALL_PATH)/StatusQ" \ + --passL:"-lStatusQ" \ --passL:"-L$(STATUSKEYCARDGO_LIBDIR)" \ --passL:"-lkeycard" \ --passL:"$(QRCODEGEN)" \ @@ -690,8 +692,6 @@ $(STATUS_CLIENT_DMG): nim_status_client $(DMG_TOOL) cp -R $(FLEETS_FILE) $(MACOS_OUTER_BUNDLE)/Contents/ mkdir -p $(MACOS_OUTER_BUNDLE)/Contents/i18n cp bin/i18n/* $(MACOS_OUTER_BUNDLE)/Contents/i18n - mkdir -p $(MACOS_OUTER_BUNDLE)/Contents/MacOS/StatusQ - cp bin/StatusQ/* $(MACOS_OUTER_BUNDLE)/Contents/MacOS/StatusQ echo -e $(BUILD_MSG) "app" macdeployqt \ @@ -753,17 +753,16 @@ $(STATUS_CLIENT_EXE): OUTPUT := tmp/windows/dist/Status $(STATUS_CLIENT_EXE): INSTALLER_OUTPUT := pkg $(STATUS_CLIENT_EXE): compile_windows_resources nim_status_client nim_windows_launcher $(NIM_WINDOWS_PREBUILT_DLLS) rm -rf pkg/*.exe tmp/windows/dist - mkdir -p $(OUTPUT)/bin $(OUTPUT)/resources $(OUTPUT)/vendor $(OUTPUT)/resources/i18n $(OUTPUT)/bin/StatusQ + mkdir -p $(OUTPUT)/bin $(OUTPUT)/resources $(OUTPUT)/vendor $(OUTPUT)/resources/i18n cat windows-install.txt | unix2dos > $(OUTPUT)/INSTALL.txt cp status.ico status.png resources.rcc $(FLEETS_FILE) $(OUTPUT)/resources/ cp bin/i18n/* $(OUTPUT)/resources/i18n cp cacert.pem $(OUTPUT)/bin/cacert.pem - cp bin/StatusQ/* $(OUTPUT)/bin/StatusQ cp bin/nim_status_client.exe $(OUTPUT)/bin/Status.exe cp bin/nim_windows_launcher.exe $(OUTPUT)/Status.exe rcedit $(OUTPUT)/bin/Status.exe --set-icon $(OUTPUT)/resources/status.ico rcedit $(OUTPUT)/Status.exe --set-icon $(OUTPUT)/resources/status.ico - cp $(DOTHERSIDE_LIBFILE) $(STATUSGO) $(STATUSKEYCARDGO) tmp/windows/tools/*.dll $(OUTPUT)/bin/ + cp $(DOTHERSIDE_LIBFILE) $(STATUSGO) $(STATUSKEYCARDGO) $(STATUSQ_INSTALL_PATH)/StatusQ/* tmp/windows/tools/*.dll $(OUTPUT)/bin/ cp "$(shell which libgcc_s_seh-1.dll)" $(OUTPUT)/bin/ cp "$(shell which libwinpthread-1.dll)" $(OUTPUT)/bin/ echo -e $(BUILD_MSG) "deployable folder" @@ -827,12 +826,12 @@ ICON_TOOL := node_modules/.bin/fileicon run-linux: nim_status_client echo -e "\033[92mRunning:\033[39m bin/nim_status_client" - LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH)" \ + LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \ ./bin/nim_status_client $(ARGS) run-linux-gdb: nim_status_client echo -e "\033[92mRunning:\033[39m bin/nim_status_client" - LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH)" \ + LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(LD_LIBRARY_PATH)" \ gdb -ex=r ./bin/nim_status_client $(ARGS) run-macos: nim_status_client @@ -848,7 +847,7 @@ run-macos: nim_status_client run-windows: STATUS_RC_FILE = status-dev.rc run-windows: compile_windows_resources nim_status_client $(NIM_WINDOWS_PREBUILT_DLLS) echo -e "\033[92mRunning:\033[39m bin/nim_status_client.exe" - PATH="$(DOTHERSIDE_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(shell pwd)"/"$(shell dirname "$(NIM_WINDOWS_PREBUILT_DLLS)")":"$(PATH)" \ + PATH="$(DOTHERSIDE_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR)":"$(STATUSQ_INSTALL_PATH)/StatusQ":"$(shell pwd)"/"$(shell dirname "$(NIM_WINDOWS_PREBUILT_DLLS)")":"$(PATH)" \ ./bin/nim_status_client.exe $(ARGS) NIM_TEST_FILES := $(wildcard test/nim/*.nim) diff --git a/config.nims b/config.nims index c27f347cca..aad3c13316 100644 --- a/config.nims +++ b/config.nims @@ -17,6 +17,7 @@ if defined(macosx): switch("passL", "-rpath" & " " & getEnv("QT5_LIBDIR")) switch("passL", "-rpath" & " " & getEnv("STATUSGO_LIBDIR")) switch("passL", "-rpath" & " " & getEnv("STATUSKEYCARDGO_LIBDIR")) + switch("passL", "-rpath" & " " & getEnv("STATUSQ_INSTALL_PATH") & "/StatusQ") # statically link these libs switch("passL", "bottles/openssl@1.1/lib/libcrypto.a") switch("passL", "bottles/openssl@1.1/lib/libssl.a") diff --git a/scripts/fix_app_dir.sh b/scripts/fix_app_dir.sh index 5d32089e0f..39e1d66a9a 100755 --- a/scripts/fix_app_dir.sh +++ b/scripts/fix_app_dir.sh @@ -6,7 +6,7 @@ set -e pipefail if [[ ! -z "${IN_NIX_SHELL}" ]]; then patchelf --set-rpath '$ORIGIN/../../lib' \ "${APP_DIR}/usr/plugins/platforminputcontexts/libfcitx5platforminputcontextplugin.so" \ - "${APP_DIR}/usr/bin/StatusQ/libStatusQ.so" + "${APP_DIR}/usr/lib/libStatusQ.so" patchelf --set-rpath '$ORIGIN' \ "${APP_DIR}/usr/lib/libcom_err.so.3" \ diff --git a/scripts/init_app_dir.sh b/scripts/init_app_dir.sh index 4c3e6fa0ef..b767529ee0 100755 --- a/scripts/init_app_dir.sh +++ b/scripts/init_app_dir.sh @@ -9,11 +9,10 @@ mkdir -p \ "${APP_DIR}/usr/lib" \ "${APP_DIR}/usr/qml" \ "${APP_DIR}/usr/i18n" \ - "${APP_DIR}/usr/bin/StatusQ" \ "${APP_DIR}/usr/plugins/platforminputcontexts" cp bin/nim_status_client "${APP_DIR}/usr/bin" -cp bin/StatusQ/* "${APP_DIR}/usr/bin/StatusQ" +cp bin/StatusQ/* "${APP_DIR}/usr/lib" cp nim-status.desktop "${APP_DIR}/." cp status.png "${APP_DIR}/status.png" cp status.png "${APP_DIR}/usr/" diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index 974b3b8ac6..257e4ca71b 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -4,11 +4,13 @@ import status_go import keycard_go import app/core/main import constants as main_constants +import statusq_bridge import app/global/global_singleton import app/global/local_app_settings import app/boot/app_controller + when defined(macosx) and defined(arm64): import posix @@ -211,6 +213,8 @@ proc mainProc() = # Ensure we have the featureFlags instance available from the start singletonInstance.engine.setRootContextProperty("featureFlagsRootContextProperty", newQVariant(singletonInstance.featureFlags())) + statusq_registerQmlTypes() + app.installEventFilter(osThemeEvent) app.installEventFilter(urlSchemeEvent) diff --git a/src/statusq_bridge.nim b/src/statusq_bridge.nim new file mode 100644 index 0000000000..b25947b099 --- /dev/null +++ b/src/statusq_bridge.nim @@ -0,0 +1,3 @@ +# Declarations of methods exposed from StatusQ + +proc statusq_registerQmlTypes*() {.cdecl, importc.} diff --git a/storybook/CMakeLists.txt b/storybook/CMakeLists.txt index 1d641c53e8..9f35efdfe4 100644 --- a/storybook/CMakeLists.txt +++ b/storybook/CMakeLists.txt @@ -76,13 +76,11 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE ) target_link_libraries( - ${PROJECT_LIB} PUBLIC Qt5::Core Qt5::Gui Qt5::Quick Qt5::QuickControls2 Qt5::WebView) + ${PROJECT_LIB} PUBLIC Qt5::Core Qt5::Gui Qt5::Quick Qt5::QuickControls2 Qt5::WebView StatusQ) target_link_libraries( ${PROJECT_NAME} PRIVATE ${PROJECT_LIB}) -add_dependencies(${PROJECT_NAME} StatusQ) - enable_testing() add_executable( @@ -91,9 +89,7 @@ add_executable( ) target_link_libraries( - PagesValidator PUBLIC Qt5::Core Qt5::Gui Qt5::Quick Qt5::QuickControls2 Qt5::WebView) - -add_dependencies(PagesValidator StatusQ) + PagesValidator PUBLIC Qt5::Core Qt5::Gui Qt5::Quick Qt5::QuickControls2 Qt5::WebView StatusQ) target_compile_definitions(PagesValidator PRIVATE QML_IMPORT_ROOT="${CMAKE_CURRENT_LIST_DIR}" @@ -114,8 +110,6 @@ add_executable(QmlTests qmlTests/main.cpp ${TEST_QML_FILES}) -add_dependencies(QmlTests StatusQ) - target_compile_definitions(QmlTests PRIVATE QML_IMPORT_ROOT="${CMAKE_CURRENT_LIST_DIR}" STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}" diff --git a/storybook/main.cpp b/storybook/main.cpp index 5eddacf792..df1b50305c 100644 --- a/storybook/main.cpp +++ b/storybook/main.cpp @@ -17,6 +17,8 @@ #include +#include + struct PagesModelInitialized : public PagesModel { explicit PagesModelInitialized(QObject *parent = nullptr) : PagesModel(QML_IMPORT_ROOT + QStringLiteral("/pages"), parent) {} @@ -102,6 +104,8 @@ int main(int argc, char *argv[]) return new SystemUtils; }); + registerStatusQTypes(); + loadContextPropertiesMocks(QML_IMPORT_ROOT, engine); #ifdef Q_OS_WIN const QUrl url(QUrl::fromLocalFile(QML_IMPORT_ROOT + QStringLiteral("/main.qml"))); @@ -147,4 +151,4 @@ void loadContextPropertiesMocks(const char* storybookRoot, QQmlApplicationEngine engine.rootContext()->setContextProperty(contextPropertyName, obj); } } -} \ No newline at end of file +} diff --git a/storybook/qmlTests/main.cpp b/storybook/qmlTests/main.cpp index 7997e50b6f..12851b592b 100644 --- a/storybook/qmlTests/main.cpp +++ b/storybook/qmlTests/main.cpp @@ -1,6 +1,8 @@ #include #include +#include + class Setup : public QObject { Q_OBJECT @@ -25,6 +27,8 @@ public slots: for (const auto& path : additionalImportPaths) engine->addImportPath(path); + registerStatusQTypes(); + QStandardPaths::setTestModeEnabled(true); QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); diff --git a/storybook/validator_main.cpp b/storybook/validator_main.cpp index a9050f3b0c..18dbed1ae1 100644 --- a/storybook/validator_main.cpp +++ b/storybook/validator_main.cpp @@ -1,7 +1,8 @@ +#include #include #include -#include +#include int main(int argc, char *argv[]) { @@ -53,6 +54,7 @@ int main(int argc, char *argv[]) auto fileName = fileInfo.filePath(); qInfo() << ">>> Checking StoryBook page:" << fileName; + registerStatusQTypes(); engine.load(fileName); } diff --git a/ui/StatusQ/CMakeLists.txt b/ui/StatusQ/CMakeLists.txt index bb45cade8c..0794b6b380 100644 --- a/ui/StatusQ/CMakeLists.txt +++ b/ui/StatusQ/CMakeLists.txt @@ -23,7 +23,7 @@ set(QZXING_MULTIMEDIA ON) set(QZXING_USE_DECODER_QR_CODE ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) find_package(Qt5 COMPONENTS @@ -48,11 +48,9 @@ if (NOT DEFINED STATUSQ_SHADOW_BUILD) # # This is an option that defaults to OFF in Debug mode and ON otherwise. # When ON: - # - resources are compiled into plugin - # - plugin is compiled in the ${CMAKE_BINARY_DIR}/StatusQ + # - resources are compiled into a a shared library # When OFF: # - no resources are compiled, it's expected to use QML/JS sources - # - the plugin is compiled in src directory # # STATUSQ_SHADOW_BUILD mode is created for sandbox/storybook hot reloading # without copying all qml files to build directory. @@ -71,15 +69,12 @@ endif() set(STATUSQ_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/StatusQ") if (${STATUSQ_SHADOW_BUILD}) - set(STATUSQ_MODULE_PATH "${CMAKE_BINARY_DIR}/bin/StatusQ") set(STATUSQ_MODULE_IMPORT_PATH ":/") else() - set(STATUSQ_MODULE_PATH "${STATUSQ_SOURCE_PATH}") set(STATUSQ_MODULE_IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src") endif() if (NOT PROJECT_IS_TOP_LEVEL) - set(STATUSQ_MODULE_PATH "${STATUSQ_MODULE_PATH}" PARENT_SCOPE) set(STATUSQ_MODULE_IMPORT_PATH "${STATUSQ_MODULE_IMPORT_PATH}" PARENT_SCOPE) set(STATUSQ_SHADOW_BUILD "${STATUSQ_SHADOW_BUILD}" PARENT_SCOPE) endif () @@ -123,6 +118,7 @@ add_library(StatusQ SHARED include/StatusQ/stringutilsinternal.h include/StatusQ/sumaggregator.h include/StatusQ/systemutilsinternal.h + include/StatusQ/typesregistration.h include/StatusQ/undefinedfilter.h include/StatusQ/urlutils.h include/StatusQ/writableproxymodel.h @@ -130,6 +126,7 @@ add_library(StatusQ SHARED src/clipboardutils.cpp src/concatmodel.cpp src/constantrole.cpp + src/externc.cpp src/fastexpressionfilter.cpp src/fastexpressionrole.cpp src/fastexpressionsorter.cpp @@ -145,7 +142,6 @@ add_library(StatusQ SHARED src/networkchecker.cpp src/objectproxymodel.cpp src/permissionutilsinternal.cpp - src/plugin.cpp src/rolesrenamingmodel.cpp src/rxvalidator.cpp src/singleroleaggregator.cpp @@ -157,6 +153,7 @@ add_library(StatusQ SHARED src/stringutilsinternal.cpp src/sumaggregator.cpp src/systemutilsinternal.cpp + src/typesregistration.cpp src/undefinedfilter.cpp src/urlutils.cpp src/writableproxymodel.cpp @@ -172,14 +169,6 @@ add_library(StatusQ SHARED target_compile_features(StatusQ PRIVATE cxx_std_17) -set_target_properties(StatusQ PROPERTIES - ADDITIONAL_CLEAN_FILES bin/StatusQ/qmldir - RUNTIME_OUTPUT_DIRECTORY ${STATUSQ_MODULE_PATH} - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${STATUSQ_MODULE_PATH} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${STATUSQ_MODULE_PATH} - LIBRARY_OUTPUT_DIRECTORY ${STATUSQ_MODULE_PATH} -) - if (APPLE) find_library(AppKit AppKit) find_library(Foundation Foundation) @@ -189,18 +178,6 @@ else () target_sources(StatusQ PRIVATE src/statuswindow_other.cpp) endif () -if (${STATUSQ_SHADOW_BUILD}) - set(COPY_QMLDIR_COMMAND - ${CMAKE_COMMAND} -E copy - ${STATUSQ_SOURCE_PATH}/qmldir - ${STATUSQ_MODULE_PATH}/qmldir) - add_custom_command( - TARGET StatusQ - POST_BUILD - COMMAND ${COPY_QMLDIR_COMMAND} - COMMENT "Copying qmldir to binary directory") -endif () - target_link_libraries(StatusQ PRIVATE Qt5::Core Qt5::Qml @@ -224,10 +201,6 @@ install(TARGETS StatusQ LIBRARY DESTINATION StatusQ ) -install(FILES src/StatusQ/qmldir - DESTINATION StatusQ - ) - # https://doc.qt.io/qtcreator/creator-qml-modules-with-plugins.html#importing-qml-modules set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/src;${QML_IMPORT_PATH} diff --git a/ui/StatusQ/include/StatusQ/stringutilsinternal.h b/ui/StatusQ/include/StatusQ/stringutilsinternal.h index 6ce8f44e57..7c597d8fe2 100644 --- a/ui/StatusQ/include/StatusQ/stringutilsinternal.h +++ b/ui/StatusQ/include/StatusQ/stringutilsinternal.h @@ -3,15 +3,12 @@ #include #include -class QJSEngine; -class QQmlEngine; - class StringUtilsInternal : public QObject { Q_OBJECT public: - explicit StringUtilsInternal(QQmlEngine* engine, QObject* parent = nullptr); + explicit StringUtilsInternal(QObject* parent = nullptr); Q_INVOKABLE QString escapeHtml(const QString& unsafe) const; @@ -20,7 +17,4 @@ public: Q_INVOKABLE QString extractDomainFromLink(const QString& link) const; Q_INVOKABLE QString plainText(const QString& htmlFragment) const; - -private: - QQmlEngine* m_engine{nullptr}; }; diff --git a/ui/StatusQ/include/StatusQ/typesregistration.h b/ui/StatusQ/include/StatusQ/typesregistration.h new file mode 100644 index 0000000000..eec3d1583c --- /dev/null +++ b/ui/StatusQ/include/StatusQ/typesregistration.h @@ -0,0 +1,3 @@ +#pragma once + +void registerStatusQTypes(); diff --git a/ui/StatusQ/sandbox/CMakeLists.txt b/ui/StatusQ/sandbox/CMakeLists.txt index 4279d17af4..a738c89b4f 100644 --- a/ui/StatusQ/sandbox/CMakeLists.txt +++ b/ui/StatusQ/sandbox/CMakeLists.txt @@ -22,7 +22,6 @@ add_executable(${PROJECT_NAME} target_compile_definitions(${PROJECT_NAME} PRIVATE SANDBOX_SRC_DIR="${CMAKE_CURRENT_LIST_DIR}" - STATUSQ_MODULE_PATH="${STATUSQ_MODULE_PATH}" STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}" ) @@ -30,4 +29,5 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 + StatusQ ) diff --git a/ui/StatusQ/sandbox/demoapp/ChatChannelView.qml b/ui/StatusQ/sandbox/demoapp/ChatChannelView.qml index 631d06c01b..875015c1ad 100644 --- a/ui/StatusQ/sandbox/demoapp/ChatChannelView.qml +++ b/ui/StatusQ/sandbox/demoapp/ChatChannelView.qml @@ -26,7 +26,6 @@ ListView { hasMention: model.hasMention isPinned: model.isPinned pinnedBy: model.pinnedBy - hasExpired: model.hasExpired reactionsModel: model.reactions || [] messageDetails: StatusMessageDetails { diff --git a/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml b/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml index df764e5a85..073c45dedb 100644 --- a/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml +++ b/ui/StatusQ/sandbox/demoapp/StatusAppCommunityView.qml @@ -320,10 +320,6 @@ StatusSectionLayout { isVerified: model.isVerified isUntrustworthy: model.isUntrustworthy isContact: model.isContact - asset.name: model.icon - asset.isImage: (asset.name !== "") - asset.isLetterIdenticon: (asset.name === "") - asset.imgIsIdenticon: false status: model.onlineStatus } } diff --git a/ui/StatusQ/sandbox/sandboxapp.cpp b/ui/StatusQ/sandbox/sandboxapp.cpp index ed437ceaa0..fd2af2b0f9 100644 --- a/ui/StatusQ/sandbox/sandboxapp.cpp +++ b/ui/StatusQ/sandbox/sandboxapp.cpp @@ -5,9 +5,13 @@ #include #include +#include + SandboxApp::SandboxApp(int &argc, char **argv) : QGuiApplication(argc, argv) { + registerStatusQTypes(); + #ifdef QT_DEBUG connect(&m_watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString& path) { qDebug().noquote() << QString("File change detected in '%1'").arg(path); @@ -34,7 +38,7 @@ void SandboxApp::startEngine() { #ifdef QT_DEBUG watchDirectoryChanges(SANDBOX_SRC_DIR); - watchDirectoryChanges(STATUSQ_MODULE_PATH); + watchDirectoryChanges(STATUSQ_MODULE_IMPORT_PATH); #endif restartEngine(); } diff --git a/ui/StatusQ/sanity_checker/CMakeLists.txt b/ui/StatusQ/sanity_checker/CMakeLists.txt index b9e36d1375..1110b8cc31 100644 --- a/ui/StatusQ/sanity_checker/CMakeLists.txt +++ b/ui/StatusQ/sanity_checker/CMakeLists.txt @@ -8,15 +8,12 @@ add_executable(${PROJECT_NAME} main.cpp ) -add_dependencies(${PROJECT_NAME} - StatusQ) - target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core - Qt5::Quick) + Qt5::Quick + StatusQ) target_compile_definitions(${PROJECT_NAME} PRIVATE - STATUSQ_MODULE_PATH="${STATUSQ_MODULE_PATH}" STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}" ) @@ -24,4 +21,4 @@ if (STATUSQ_SHADOW_BUILD) target_compile_definitions(${PROJECT_NAME} PRIVATE STATUSQ_SHADOW_BUILD ) -endif () \ No newline at end of file +endif () diff --git a/ui/StatusQ/sanity_checker/main.cpp b/ui/StatusQ/sanity_checker/main.cpp index 0de0a7370a..af7b928b20 100644 --- a/ui/StatusQ/sanity_checker/main.cpp +++ b/ui/StatusQ/sanity_checker/main.cpp @@ -4,6 +4,8 @@ #include #include +#include + int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlEngine engine; @@ -17,18 +19,7 @@ int main(int argc, char *argv[]) { const QString iterationPath{QStringLiteral(STATUSQ_MODULE_IMPORT_PATH)}; engine.addImportPath(iterationPath); - // Create a dummy component with StatusQ import. - // NOTE: https://github.com/status-im/status-desktop/issues/10218 - - QQmlComponent mainComponent(&engine); - mainComponent.setData("import QtQuick 2.15\nimport StatusQ 0.1\nItem { }", {}); - - if (mainComponent.isError()) { - qWarning() << "Failed to import StatusQ 0.1:" << mainComponent.errors(); - return EXIT_FAILURE; - } - - // Start iterating over directory + registerStatusQTypes(); bool errorsFound = false; diff --git a/ui/StatusQ/src/StatusQ/qmldir b/ui/StatusQ/src/StatusQ/qmldir deleted file mode 100644 index 12303d4087..0000000000 --- a/ui/StatusQ/src/StatusQ/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module StatusQ -plugin StatusQ -classname StatusQPlugin diff --git a/ui/StatusQ/src/externc.cpp b/ui/StatusQ/src/externc.cpp new file mode 100644 index 0000000000..f99f49f6cc --- /dev/null +++ b/ui/StatusQ/src/externc.cpp @@ -0,0 +1,11 @@ +#include + +#include + +extern "C" { + +Q_DECL_EXPORT void statusq_registerQmlTypes() { + registerStatusQTypes(); +} + +} // extern "C" diff --git a/ui/StatusQ/src/plugin.cpp b/ui/StatusQ/src/plugin.cpp deleted file mode 100644 index 796fb4dc1b..0000000000 --- a/ui/StatusQ/src/plugin.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include - -#include -#include - -#include "StatusQ/clipboardutils.h" -#include "StatusQ/concatmodel.h" -#include "StatusQ/constantrole.h" -#include "StatusQ/fastexpressionfilter.h" -#include "StatusQ/fastexpressionrole.h" -#include "StatusQ/fastexpressionsorter.h" -#include "StatusQ/formatteddoubleproperty.h" -#include "StatusQ/functionaggregator.h" -#include "StatusQ/genericvalidator.h" -#include "StatusQ/groupingmodel.h" -#include "StatusQ/leftjoinmodel.h" -#include "StatusQ/modelcount.h" -#include "StatusQ/modelentry.h" -#include "StatusQ/modelutilsinternal.h" -#include "StatusQ/movablemodel.h" -#include "StatusQ/networkchecker.h" -#include "StatusQ/objectproxymodel.h" -#include "StatusQ/permissionutilsinternal.h" -#include "StatusQ/rolesrenamingmodel.h" -#include "StatusQ/rxvalidator.h" -#include "StatusQ/snapshotobject.h" -#include "StatusQ/statusemojimodel.h" -#include "StatusQ/statussyntaxhighlighter.h" -#include "StatusQ/statuswindow.h" -#include "StatusQ/stringutilsinternal.h" -#include "StatusQ/sumaggregator.h" -#include "StatusQ/systemutilsinternal.h" -#include "StatusQ/undefinedfilter.h" -#include "StatusQ/urlutils.h" -#include "StatusQ/writableproxymodel.h" - - -#include "wallet/managetokenscontroller.h" -#include "wallet/managetokensmodel.h" - -class StatusQPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) -public: - void registerTypes(const char* uri) override - { - Q_ASSERT(uri == QLatin1String("StatusQ")); - - qmlRegisterType("StatusQ", 0, 1, "StatusWindow"); - qmlRegisterType("StatusQ", 0, 1, "StatusSyntaxHighlighter"); - qmlRegisterType("StatusQ", 0, 1, "RXValidator"); - - qmlRegisterUncreatableType( - "StatusQ", 0, 1, - "Validator", "This is abstract type, cannot be created directly."); - qmlRegisterType("StatusQ", 0, 1, "GenericValidator"); - - qmlRegisterType("StatusQ.Models", 0, 1, "ManageTokensController"); - qmlRegisterType("StatusQ.Models", 0, 1, "ManageTokensModel"); - - qmlRegisterType("StatusQ", 0, 1, "GroupingModel"); - qmlRegisterType("StatusQ", 0, 1, "SourceModel"); - qmlRegisterType("StatusQ", 0, 1, "ConcatModel"); - qmlRegisterType("StatusQ", 0, 1, "MovableModel"); - qmlRegisterType("StatusQ", 0, 1, "NetworkChecker"); - - qmlRegisterType("StatusQ", 0, 1, "FastExpressionFilter"); - qmlRegisterType("StatusQ", 0, 1, "FastExpressionRole"); - qmlRegisterType("StatusQ", 0, 1, "FastExpressionSorter"); - qmlRegisterType("StatusQ", 0, 1, "UndefinedFilter"); - qmlRegisterType("StatusQ", 0, 1, "ConstantRole"); - - qmlRegisterType("StatusQ", 0, 1, "ObjectProxyModel"); - qmlRegisterType("StatusQ", 0, 1, "LeftJoinModel"); - qmlRegisterType("StatusQ", 0, 1, "RoleRename"); - qmlRegisterType("StatusQ", 0, 1, "RolesRenamingModel"); - qmlRegisterType("StatusQ", 0, 1, "StatusEmojiModel"); - qmlRegisterType("StatusQ", 0, 1, "SumAggregator"); - qmlRegisterType("StatusQ", 0, 1, "FunctionAggregator"); - qmlRegisterType("StatusQ", 0, 1, "WritableProxyModel"); - qmlRegisterType("StatusQ", 0, 1, "FormattedDoubleProperty"); - - qmlRegisterSingletonType("StatusQ", 0, 1, "ClipboardUtils", &ClipboardUtils::qmlInstance); - qmlRegisterSingletonType("StatusQ", 0, 1, "UrlUtils", &UrlUtils::qmlInstance); - - qmlRegisterType("StatusQ", 0, 1, "ModelEntry"); - qmlRegisterType("StatusQ", 0, 1, "SnapshotObject"); - - qmlRegisterUncreatableType("StatusQ", 0, 1, - "ModelCount", "This is attached type, cannot be created directly."); - - // Workaround for https://bugreports.qt.io/browse/QTBUG-86428 - qmlRegisterAnonymousType("StatusQ", 1); - - qmlRegisterSingletonType( - "StatusQ.Internal", 0, 1, "ModelUtils", &ModelUtilsInternal::qmlInstance); - - qmlRegisterSingletonType( - "StatusQ.Internal", 0, 1, "StringUtils", [](QQmlEngine* engine, QJSEngine*) { - return new StringUtilsInternal(engine); - }); - - qmlRegisterSingletonType( - "StatusQ.Core", 0, 1, "SystemUtils", [](QQmlEngine*, QJSEngine*) { - return new SystemUtilsInternal; - }); - - qmlRegisterSingletonType( - "StatusQ.Internal", 0, 1, "PermissionUtils", [](QQmlEngine*, QJSEngine*) { - return new PermissionUtilsInternal; - }); - - QZXing::registerQMLTypes(); - qqsfpm::registerTypes(); - } -}; - -#include "plugin.moc" diff --git a/ui/StatusQ/src/stringutilsinternal.cpp b/ui/StatusQ/src/stringutilsinternal.cpp index bf0f1f8cc3..ebd03588f1 100644 --- a/ui/StatusQ/src/stringutilsinternal.cpp +++ b/ui/StatusQ/src/stringutilsinternal.cpp @@ -7,15 +7,7 @@ #include #include -StringUtilsInternal::StringUtilsInternal(QQmlEngine* engine, QObject* parent) - : m_engine(engine) - , QObject(parent) -{ } - -QString StringUtilsInternal::escapeHtml(const QString& unsafe) const -{ - return unsafe.toHtmlEscaped(); -} +namespace { QString resolveFileUsingQmlImportPaths(QQmlEngine *engine, const QString &relativeFilePath) { const auto importPaths = engine->importPathList(); @@ -29,9 +21,22 @@ QString resolveFileUsingQmlImportPaths(QQmlEngine *engine, const QString &relati return {}; } +} // unnamed namespace + +StringUtilsInternal::StringUtilsInternal(QObject* parent) : QObject(parent) +{ +} + +QString StringUtilsInternal::escapeHtml(const QString& unsafe) const +{ + return unsafe.toHtmlEscaped(); +} + QString StringUtilsInternal::readTextFile(const QString& filePath) const { - auto selector = QQmlFileSelector::get(m_engine); + auto engine = qmlEngine(this); + + auto selector = QQmlFileSelector::get(engine); if (!selector) { qWarning() << Q_FUNC_INFO << "No QQmlFileSelector available to load text file:" << filePath; return {}; @@ -50,7 +55,7 @@ QString StringUtilsInternal::readTextFile(const QString& filePath) const QFile file(selectedFilePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - const auto resolvedFilePath = resolveFileUsingQmlImportPaths(m_engine, filePath); + const auto resolvedFilePath = resolveFileUsingQmlImportPaths(engine, filePath); if (resolvedFilePath.isEmpty()) { qWarning() << Q_FUNC_INFO << "Can't find file in QML import paths" << filePath; return {}; @@ -75,7 +80,7 @@ QString StringUtilsInternal::extractDomainFromLink(const QString& link) const return url.host(); } -QString StringUtilsInternal::plainText(const QString &htmlFragment) const +QString StringUtilsInternal::plainText(const QString& htmlFragment) const { return QTextDocumentFragment::fromHtml(htmlFragment).toPlainText(); } diff --git a/ui/StatusQ/src/typesregistration.cpp b/ui/StatusQ/src/typesregistration.cpp new file mode 100644 index 0000000000..e64e15478b --- /dev/null +++ b/ui/StatusQ/src/typesregistration.cpp @@ -0,0 +1,105 @@ +#include +#include + +#include "StatusQ/clipboardutils.h" +#include "StatusQ/concatmodel.h" +#include "StatusQ/constantrole.h" +#include "StatusQ/fastexpressionfilter.h" +#include "StatusQ/fastexpressionrole.h" +#include "StatusQ/fastexpressionsorter.h" +#include "StatusQ/formatteddoubleproperty.h" +#include "StatusQ/functionaggregator.h" +#include "StatusQ/genericvalidator.h" +#include "StatusQ/groupingmodel.h" +#include "StatusQ/leftjoinmodel.h" +#include "StatusQ/modelcount.h" +#include "StatusQ/modelentry.h" +#include "StatusQ/modelutilsinternal.h" +#include "StatusQ/movablemodel.h" +#include "StatusQ/networkchecker.h" +#include "StatusQ/objectproxymodel.h" +#include "StatusQ/permissionutilsinternal.h" +#include "StatusQ/rolesrenamingmodel.h" +#include "StatusQ/rxvalidator.h" +#include "StatusQ/snapshotobject.h" +#include "StatusQ/statusemojimodel.h" +#include "StatusQ/statussyntaxhighlighter.h" +#include "StatusQ/statuswindow.h" +#include "StatusQ/stringutilsinternal.h" +#include "StatusQ/sumaggregator.h" +#include "StatusQ/systemutilsinternal.h" +#include "StatusQ/undefinedfilter.h" +#include "StatusQ/urlutils.h" +#include "StatusQ/writableproxymodel.h" + +#include "wallet/managetokenscontroller.h" +#include "wallet/managetokensmodel.h" + +void registerStatusQTypes() { + qmlRegisterType("StatusQ", 0, 1, "StatusWindow"); + qmlRegisterType("StatusQ", 0, 1, "StatusSyntaxHighlighter"); + qmlRegisterType("StatusQ", 0, 1, "RXValidator"); + + qmlRegisterUncreatableType( + "StatusQ", 0, 1, + "Validator", "This is abstract type, cannot be created directly."); + qmlRegisterType("StatusQ", 0, 1, "GenericValidator"); + + qmlRegisterType("StatusQ.Models", 0, 1, "ManageTokensController"); + qmlRegisterType("StatusQ.Models", 0, 1, "ManageTokensModel"); + + qmlRegisterType("StatusQ", 0, 1, "GroupingModel"); + qmlRegisterType("StatusQ", 0, 1, "SourceModel"); + qmlRegisterType("StatusQ", 0, 1, "ConcatModel"); + qmlRegisterType("StatusQ", 0, 1, "MovableModel"); + qmlRegisterType("StatusQ", 0, 1, "NetworkChecker"); + + qmlRegisterType("StatusQ", 0, 1, "FastExpressionFilter"); + qmlRegisterType("StatusQ", 0, 1, "FastExpressionRole"); + qmlRegisterType("StatusQ", 0, 1, "FastExpressionSorter"); + qmlRegisterType("StatusQ", 0, 1, "UndefinedFilter"); + qmlRegisterType("StatusQ", 0, 1, "ConstantRole"); + + qmlRegisterType("StatusQ", 0, 1, "ObjectProxyModel"); + qmlRegisterType("StatusQ", 0, 1, "LeftJoinModel"); + qmlRegisterType("StatusQ", 0, 1, "RoleRename"); + qmlRegisterType("StatusQ", 0, 1, "RolesRenamingModel"); + qmlRegisterType("StatusQ", 0, 1, "StatusEmojiModel"); + qmlRegisterType("StatusQ", 0, 1, "SumAggregator"); + qmlRegisterType("StatusQ", 0, 1, "FunctionAggregator"); + qmlRegisterType("StatusQ", 0, 1, "WritableProxyModel"); + qmlRegisterType("StatusQ", 0, 1, "FormattedDoubleProperty"); + + qmlRegisterSingletonType("StatusQ", 0, 1, "ClipboardUtils", &ClipboardUtils::qmlInstance); + qmlRegisterSingletonType("StatusQ", 0, 1, "UrlUtils", &UrlUtils::qmlInstance); + + qmlRegisterType("StatusQ", 0, 1, "ModelEntry"); + qmlRegisterType("StatusQ", 0, 1, "SnapshotObject"); + + qmlRegisterUncreatableType("StatusQ", 0, 1, + "ModelCount", "This is attached type, cannot be created directly."); + + // Workaround for https://bugreports.qt.io/browse/QTBUG-86428 + qmlRegisterAnonymousType("StatusQ", 1); + + qmlRegisterSingletonType( + "StatusQ.Internal", 0, 1, "ModelUtils", &ModelUtilsInternal::qmlInstance); + + qmlRegisterSingletonType( + "StatusQ.Internal", 0, 1, "StringUtils", [](QQmlEngine* engine, QJSEngine*) { + return new StringUtilsInternal(engine); + }); + + qmlRegisterSingletonType( + "StatusQ.Core", 0, 1, "SystemUtils", [](QQmlEngine*, QJSEngine*) { + return new SystemUtilsInternal; + }); + + qmlRegisterSingletonType( + "StatusQ.Internal", 0, 1, "PermissionUtils", [](QQmlEngine*, QJSEngine*) { + return new PermissionUtilsInternal; + }); + + QZXing::registerQMLTypes(); + qqsfpm::registerTypes(); +} diff --git a/ui/StatusQ/tests/CMakeLists.txt b/ui/StatusQ/tests/CMakeLists.txt index c9f18f2f94..81e1e20862 100644 --- a/ui/StatusQ/tests/CMakeLists.txt +++ b/ui/StatusQ/tests/CMakeLists.txt @@ -40,7 +40,6 @@ file(GLOB_RECURSE TEST_QML_FILES "*.qml") add_executable(QmlTests main.cpp "${TEST_QML_FILES}") target_compile_definitions(QmlTests PRIVATE - STATUSQ_MODULE_PATH="${STATUSQ_MODULE_PATH}" STATUSQ_MODULE_IMPORT_PATH="${STATUSQ_MODULE_IMPORT_PATH}" # no need to copy around qml test files for shadow builds - just set the respective define QUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/ui/StatusQ/tests/main.cpp b/ui/StatusQ/tests/main.cpp index bc5a6d5583..3cc3a0c79f 100644 --- a/ui/StatusQ/tests/main.cpp +++ b/ui/StatusQ/tests/main.cpp @@ -6,6 +6,8 @@ #include #include +#include + class RunBeforeQApplicationIsInitialized { public: RunBeforeQApplicationIsInitialized() @@ -29,6 +31,8 @@ public slots: // TODO: Alternative to not yet supported QML_ELEMENT qmlRegisterType("StatusQ.TestHelpers", 0, 1, "MonitorQtOutput"); qmlRegisterType("StatusQ.TestHelpers", 0, 1, "ModelAccessObserverProxy"); + + registerStatusQTypes(); } };