Introduce ability of calling StatusQ methods from nim

Closes: #16496
This commit is contained in:
Michał Cieślak 2024-10-11 17:14:21 +02:00 committed by Michał
parent 14637a8709
commit f75e4e0c47
26 changed files with 190 additions and 221 deletions

View File

@ -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)

View File

@ -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")

View File

@ -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" \

View File

@ -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/"

View File

@ -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)

3
src/statusq_bridge.nim Normal file
View File

@ -0,0 +1,3 @@
# Declarations of methods exposed from StatusQ
proc statusq_registerQmlTypes*() {.cdecl, importc.}

View File

@ -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}"

View File

@ -17,6 +17,8 @@
#include <memory>
#include <StatusQ/typesregistration.h>
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")));

View File

@ -1,6 +1,8 @@
#include <QQmlEngine>
#include <QtQuickTest>
#include <StatusQ/typesregistration.h>
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));

View File

@ -1,7 +1,8 @@
#include <QDir>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDir>
#include <StatusQ/typesregistration.h>
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);
}

View File

@ -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}

View File

@ -3,15 +3,12 @@
#include <QObject>
#include <QString>
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};
};

View File

@ -0,0 +1,3 @@
#pragma once
void registerStatusQTypes();

View File

@ -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
)

View File

@ -26,7 +26,6 @@ ListView {
hasMention: model.hasMention
isPinned: model.isPinned
pinnedBy: model.pinnedBy
hasExpired: model.hasExpired
reactionsModel: model.reactions || []
messageDetails: StatusMessageDetails {

View File

@ -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
}
}

View File

@ -5,9 +5,13 @@
#include <QDebug>
#include <QDirIterator>
#include <StatusQ/typesregistration.h>
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();
}

View File

@ -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}"
)

View File

@ -4,6 +4,8 @@
#include <QQmlComponent>
#include <QQmlEngine>
#include <StatusQ/typesregistration.h>
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;

View File

@ -1,3 +0,0 @@
module StatusQ
plugin StatusQ
classname StatusQPlugin

View File

@ -0,0 +1,11 @@
#include <QtGlobal>
#include <StatusQ/typesregistration.h>
extern "C" {
Q_DECL_EXPORT void statusq_registerQmlTypes() {
registerStatusQTypes();
}
} // extern "C"

View File

@ -1,119 +0,0 @@
#include <QQmlExtensionPlugin>
#include <QZXing.h>
#include <qqmlsortfilterproxymodeltypes.h>
#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<StatusWindow>("StatusQ", 0, 1, "StatusWindow");
qmlRegisterType<StatusSyntaxHighlighter>("StatusQ", 0, 1, "StatusSyntaxHighlighter");
qmlRegisterType<RXValidator>("StatusQ", 0, 1, "RXValidator");
qmlRegisterUncreatableType<QValidator>(
"StatusQ", 0, 1,
"Validator", "This is abstract type, cannot be created directly.");
qmlRegisterType<GenericValidator>("StatusQ", 0, 1, "GenericValidator");
qmlRegisterType<ManageTokensController>("StatusQ.Models", 0, 1, "ManageTokensController");
qmlRegisterType<ManageTokensModel>("StatusQ.Models", 0, 1, "ManageTokensModel");
qmlRegisterType<GroupingModel>("StatusQ", 0, 1, "GroupingModel");
qmlRegisterType<SourceModel>("StatusQ", 0, 1, "SourceModel");
qmlRegisterType<ConcatModel>("StatusQ", 0, 1, "ConcatModel");
qmlRegisterType<MovableModel>("StatusQ", 0, 1, "MovableModel");
qmlRegisterType<NetworkChecker>("StatusQ", 0, 1, "NetworkChecker");
qmlRegisterType<FastExpressionFilter>("StatusQ", 0, 1, "FastExpressionFilter");
qmlRegisterType<FastExpressionRole>("StatusQ", 0, 1, "FastExpressionRole");
qmlRegisterType<FastExpressionSorter>("StatusQ", 0, 1, "FastExpressionSorter");
qmlRegisterType<UndefinedFilter>("StatusQ", 0, 1, "UndefinedFilter");
qmlRegisterType<ConstantRole>("StatusQ", 0, 1, "ConstantRole");
qmlRegisterType<ObjectProxyModel>("StatusQ", 0, 1, "ObjectProxyModel");
qmlRegisterType<LeftJoinModel>("StatusQ", 0, 1, "LeftJoinModel");
qmlRegisterType<RoleRename>("StatusQ", 0, 1, "RoleRename");
qmlRegisterType<RolesRenamingModel>("StatusQ", 0, 1, "RolesRenamingModel");
qmlRegisterType<StatusEmojiModel>("StatusQ", 0, 1, "StatusEmojiModel");
qmlRegisterType<SumAggregator>("StatusQ", 0, 1, "SumAggregator");
qmlRegisterType<FunctionAggregator>("StatusQ", 0, 1, "FunctionAggregator");
qmlRegisterType<WritableProxyModel>("StatusQ", 0, 1, "WritableProxyModel");
qmlRegisterType<FormattedDoubleProperty>("StatusQ", 0, 1, "FormattedDoubleProperty");
qmlRegisterSingletonType<ClipboardUtils>("StatusQ", 0, 1, "ClipboardUtils", &ClipboardUtils::qmlInstance);
qmlRegisterSingletonType<UrlUtils>("StatusQ", 0, 1, "UrlUtils", &UrlUtils::qmlInstance);
qmlRegisterType<ModelEntry>("StatusQ", 0, 1, "ModelEntry");
qmlRegisterType<SnapshotObject>("StatusQ", 0, 1, "SnapshotObject");
qmlRegisterUncreatableType<ModelCount>("StatusQ", 0, 1,
"ModelCount", "This is attached type, cannot be created directly.");
// Workaround for https://bugreports.qt.io/browse/QTBUG-86428
qmlRegisterAnonymousType<QAbstractItemModel>("StatusQ", 1);
qmlRegisterSingletonType<ModelUtilsInternal>(
"StatusQ.Internal", 0, 1, "ModelUtils", &ModelUtilsInternal::qmlInstance);
qmlRegisterSingletonType<StringUtilsInternal>(
"StatusQ.Internal", 0, 1, "StringUtils", [](QQmlEngine* engine, QJSEngine*) {
return new StringUtilsInternal(engine);
});
qmlRegisterSingletonType<SystemUtilsInternal>(
"StatusQ.Core", 0, 1, "SystemUtils", [](QQmlEngine*, QJSEngine*) {
return new SystemUtilsInternal;
});
qmlRegisterSingletonType<PermissionUtilsInternal>(
"StatusQ.Internal", 0, 1, "PermissionUtils", [](QQmlEngine*, QJSEngine*) {
return new PermissionUtilsInternal;
});
QZXing::registerQMLTypes();
qqsfpm::registerTypes();
}
};
#include "plugin.moc"

View File

@ -7,15 +7,7 @@
#include <QUrl>
#include <QTextDocumentFragment>
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();
}

View File

@ -0,0 +1,105 @@
#include <QZXing.h>
#include <qqmlsortfilterproxymodeltypes.h>
#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<StatusWindow>("StatusQ", 0, 1, "StatusWindow");
qmlRegisterType<StatusSyntaxHighlighter>("StatusQ", 0, 1, "StatusSyntaxHighlighter");
qmlRegisterType<RXValidator>("StatusQ", 0, 1, "RXValidator");
qmlRegisterUncreatableType<QValidator>(
"StatusQ", 0, 1,
"Validator", "This is abstract type, cannot be created directly.");
qmlRegisterType<GenericValidator>("StatusQ", 0, 1, "GenericValidator");
qmlRegisterType<ManageTokensController>("StatusQ.Models", 0, 1, "ManageTokensController");
qmlRegisterType<ManageTokensModel>("StatusQ.Models", 0, 1, "ManageTokensModel");
qmlRegisterType<GroupingModel>("StatusQ", 0, 1, "GroupingModel");
qmlRegisterType<SourceModel>("StatusQ", 0, 1, "SourceModel");
qmlRegisterType<ConcatModel>("StatusQ", 0, 1, "ConcatModel");
qmlRegisterType<MovableModel>("StatusQ", 0, 1, "MovableModel");
qmlRegisterType<NetworkChecker>("StatusQ", 0, 1, "NetworkChecker");
qmlRegisterType<FastExpressionFilter>("StatusQ", 0, 1, "FastExpressionFilter");
qmlRegisterType<FastExpressionRole>("StatusQ", 0, 1, "FastExpressionRole");
qmlRegisterType<FastExpressionSorter>("StatusQ", 0, 1, "FastExpressionSorter");
qmlRegisterType<UndefinedFilter>("StatusQ", 0, 1, "UndefinedFilter");
qmlRegisterType<ConstantRole>("StatusQ", 0, 1, "ConstantRole");
qmlRegisterType<ObjectProxyModel>("StatusQ", 0, 1, "ObjectProxyModel");
qmlRegisterType<LeftJoinModel>("StatusQ", 0, 1, "LeftJoinModel");
qmlRegisterType<RoleRename>("StatusQ", 0, 1, "RoleRename");
qmlRegisterType<RolesRenamingModel>("StatusQ", 0, 1, "RolesRenamingModel");
qmlRegisterType<StatusEmojiModel>("StatusQ", 0, 1, "StatusEmojiModel");
qmlRegisterType<SumAggregator>("StatusQ", 0, 1, "SumAggregator");
qmlRegisterType<FunctionAggregator>("StatusQ", 0, 1, "FunctionAggregator");
qmlRegisterType<WritableProxyModel>("StatusQ", 0, 1, "WritableProxyModel");
qmlRegisterType<FormattedDoubleProperty>("StatusQ", 0, 1, "FormattedDoubleProperty");
qmlRegisterSingletonType<ClipboardUtils>("StatusQ", 0, 1, "ClipboardUtils", &ClipboardUtils::qmlInstance);
qmlRegisterSingletonType<UrlUtils>("StatusQ", 0, 1, "UrlUtils", &UrlUtils::qmlInstance);
qmlRegisterType<ModelEntry>("StatusQ", 0, 1, "ModelEntry");
qmlRegisterType<SnapshotObject>("StatusQ", 0, 1, "SnapshotObject");
qmlRegisterUncreatableType<ModelCount>("StatusQ", 0, 1,
"ModelCount", "This is attached type, cannot be created directly.");
// Workaround for https://bugreports.qt.io/browse/QTBUG-86428
qmlRegisterAnonymousType<QAbstractItemModel>("StatusQ", 1);
qmlRegisterSingletonType<ModelUtilsInternal>(
"StatusQ.Internal", 0, 1, "ModelUtils", &ModelUtilsInternal::qmlInstance);
qmlRegisterSingletonType<StringUtilsInternal>(
"StatusQ.Internal", 0, 1, "StringUtils", [](QQmlEngine* engine, QJSEngine*) {
return new StringUtilsInternal(engine);
});
qmlRegisterSingletonType<SystemUtilsInternal>(
"StatusQ.Core", 0, 1, "SystemUtils", [](QQmlEngine*, QJSEngine*) {
return new SystemUtilsInternal;
});
qmlRegisterSingletonType<PermissionUtilsInternal>(
"StatusQ.Internal", 0, 1, "PermissionUtils", [](QQmlEngine*, QJSEngine*) {
return new PermissionUtilsInternal;
});
QZXing::registerQMLTypes();
qqsfpm::registerTypes();
}

View File

@ -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}"

View File

@ -6,6 +6,8 @@
#include <TestHelpers/MonitorQtOutput.h>
#include <TestHelpers/modelaccessobserverproxy.h>
#include <StatusQ/typesregistration.h>
class RunBeforeQApplicationIsInitialized {
public:
RunBeforeQApplicationIsInitialized()
@ -29,6 +31,8 @@ public slots:
// TODO: Alternative to not yet supported QML_ELEMENT
qmlRegisterType<MonitorQtOutput>("StatusQ.TestHelpers", 0, 1, "MonitorQtOutput");
qmlRegisterType<ModelAccessObserverProxy>("StatusQ.TestHelpers", 0, 1, "ModelAccessObserverProxy");
registerStatusQTypes();
}
};