diff --git a/.gitmodules b/.gitmodules index e5ddfac375..d997958195 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,9 +2,6 @@ path = vendor/nimbus-build-system url = https://github.com/status-im/nimbus-build-system.git branch = master -[submodule "vendor/nimqml"] - path = vendor/nimqml - url = https://github.com/status-im/nimqml.git [submodule "vendor/uuids"] path = vendor/uuids url = https://github.com/pragmagic/uuids.git @@ -124,3 +121,10 @@ [submodule "vendor/nim-intops"] path = vendor/nim-intops url = https://github.com/vacp2p/nim-intops.git +[submodule "vendor/nim-seaqt"] + path = vendor/nim-seaqt + url = https://github.com/seaqt/nim-seaqt.git + branch = qt-6.4 +[submodule "vendor/nimqml-seaqt"] + path = vendor/nimqml-seaqt + url = https://github.com/seaqt/nimqml-seaqt.git diff --git a/.pcwrap/pkg-config b/.pcwrap/pkg-config new file mode 100755 index 0000000000..7261bd59bb --- /dev/null +++ b/.pcwrap/pkg-config @@ -0,0 +1,40 @@ +#!/bin/sh +# Generic pkg-config wrapper (POSIX sh; macOS / Linux / Windows-MSYS). +# +# Forces --define-prefix so Qt's relocatable .pc files — which hard-code the +# build-host prefix (e.g. the online-installer's /Users/qt/work/install) — +# resolve ${prefix} from each .pc file's actual on-disk location instead. +# Harmless for .pc files that already carry a correct prefix. +# +# Put this directory first on PATH so it shadows the real pkg-config for both +# the Makefile's `$(shell pkg-config …)` calls and seaqt's compile-time +# `gorge("pkg-config …")` calls. +# +# The real tool is discovered from PATH at runtime (no hard-coded path): we +# drop this wrapper's own directory from PATH and then let `command -v` find +# the next pkg-config — falling back to pkgconf. This avoids infinite +# self-recursion and works regardless of where pkg-config is installed. +# +# Windows note: native (cmd.exe) builds resolve the sibling pkg-config.cmd via +# PATHEXT; this extensionless script is what MSYS/Cygwin bash picks up. + +# Absolute path of this script's directory. +self_dir=$(CDPATH= cd -- "$(dirname -- "$0")" 2>/dev/null && pwd -P) || self_dir= + +# Rebuild PATH without our own directory so the real tool resolves normally. +clean_path= +oldifs=$IFS +IFS=: +for d in $PATH; do + [ -n "$d" ] || d=. + resolved=$(CDPATH= cd -- "$d" 2>/dev/null && pwd -P) || resolved=$d + [ -n "$self_dir" ] && [ "$resolved" = "$self_dir" ] && continue + clean_path=${clean_path:+$clean_path:}$d +done +IFS=$oldifs + +real=$(PATH=$clean_path command -v pkg-config 2>/dev/null) \ + || real=$(PATH=$clean_path command -v pkgconf 2>/dev/null) \ + || { echo "pkg-config wrapper: no real pkg-config/pkgconf found on PATH" >&2; exit 127; } + +exec "$real" --define-prefix "$@" diff --git a/.pcwrap/pkg-config.cmd b/.pcwrap/pkg-config.cmd new file mode 100755 index 0000000000..6bd61eca13 --- /dev/null +++ b/.pcwrap/pkg-config.cmd @@ -0,0 +1,37 @@ +@echo off +rem Generic pkg-config wrapper for native Windows (cmd.exe). +rem +rem Windows companion to the POSIX `pkg-config` sh script in this directory. +rem When Nim's `gorge("pkg-config ...")` (or the Makefile) runs under native +rem cmd.exe, the bare name `pkg-config` resolves to THIS .cmd via PATHEXT, +rem while MSYS/Cygwin bash picks the extensionless sh script instead. +rem +rem Forces --define-prefix so Qt's relocatable .pc files resolve ${prefix} +rem from their actual on-disk location. The real pkg-config/pkgconf is found +rem from PATH at runtime (no hard-coded path) via `where`, skipping this +rem wrapper's own directory to avoid infinite self-recursion. +setlocal enableextensions enabledelayedexpansion + +set "self_dir=%~dp0" +if "%self_dir:~-1%"=="\" set "self_dir=%self_dir:~0,-1%" + +set "real=" +for %%P in (pkg-config.exe pkg-config pkgconf.exe pkgconf) do ( + if not defined real ( + for /f "delims=" %%I in ('where %%P 2^>nul') do ( + if not defined real ( + set "cand_dir=%%~dpI" + if "!cand_dir:~-1!"=="\" set "cand_dir=!cand_dir:~0,-1!" + if /I not "!cand_dir!"=="%self_dir%" set "real=%%I" + ) + ) + ) +) + +if not defined real ( + echo pkg-config wrapper: no real pkg-config/pkgconf found on PATH 1>&2 + exit /b 127 +) + +"%real%" --define-prefix %* +exit /b %errorlevel% diff --git a/Makefile b/Makefile index 5527ef9ce8..8cee5698d7 100644 --- a/Makefile +++ b/Makefile @@ -204,13 +204,26 @@ ifneq ($(QT_MAJOR_VERSION),6) $(error Detected Qt major version $(QT_MAJOR_VERSION), but version 6 is required. Please install Qt 6 and set paths accordingly.) endif +# In-repo pkg-config wrapper: forces --define-prefix so Qt's relocatable .pc +# files (which hard-code the build-host prefix, e.g. /Users/qt/work/install) +# resolve ${prefix} from the .pc file's real on-disk location. The wrapper finds +# the real pkg-config from PATH itself (skipping its own dir). Two wiring points, +# because GNU make's $(shell ...) FUNCTION ignores a makefile-level `export PATH` +# (it resolves commands via make's startup PATH) while recipe commands honor it: +# 1. PKG_CONFIG var, used in the Makefile's own $(shell pkg-config ...) calls. +# 2. export PATH, so seaqt's nim-compile-time gorge("pkg-config ...") — which +# runs inside the `nim` recipe — also hits the wrapper, on all platforms +# (native Windows resolves the sibling .pcwrap/pkg-config.cmd via PATHEXT). +PKG_CONFIG ?= $(CURDIR)/.pcwrap/pkg-config +export PATH := $(CURDIR)/.pcwrap:$(PATH) + ifneq ($(mkspecs),win32) export QT_LIBDIR := $(shell $(QMAKE) -query QT_INSTALL_LIBS 2>/dev/null) QT_QMLDIR := $(shell $(QMAKE) -query QT_INSTALL_QML 2>/dev/null) QT_INSTALL_PREFIX := $(shell $(QMAKE) -query QT_INSTALL_PREFIX 2>/dev/null) - QT_PKGCONFIG_INSTALL_PREFIX := $(shell pkg-config --variable=prefix Qt"$(QT_MAJOR_VERSION)"Core 2>/dev/null) + QT_PKGCONFIG_INSTALL_PREFIX := $(shell $(PKG_CONFIG) --variable=prefix Qt"$(QT_MAJOR_VERSION)"Core 2>/dev/null) ifeq ($(QT_INSTALL_PREFIX),$(QT_PKGCONFIG_INSTALL_PREFIX)) - QT_PCFILEDIR := $(shell pkg-config --variable=pcfiledir Qt6Core 2>/dev/null) + QT_PCFILEDIR := $(shell $(PKG_CONFIG) --variable=pcfiledir Qt6Core 2>/dev/null) else QT_PCFILEDIR := $(QT_LIBDIR)/pkgconfig endif @@ -225,8 +238,10 @@ ifneq ($(mkspecs),win32) NIM_PARAMS += --passL:"-L$(QT_LIBDIR)" endif DOTHERSIDE_LIBFILE := $(DOTHERSIDE_BUILD_PATH)/lib/libDOtherSideStatic.a - # order matters here, due to "-Wl,-as-needed" - NIM_PARAMS += --passL:"$(DOTHERSIDE_LIBFILE)" --passL:"$(shell PKG_CONFIG_PATH="$(QT_PCFILEDIR)" pkg-config --libs Qt"$(QT_MAJOR_VERSION)"Core Qt"$(QT_MAJOR_VERSION)"Qml Qt"$(QT_MAJOR_VERSION)"Gui Qt"$(QT_MAJOR_VERSION)"Quick Qt"$(QT_MAJOR_VERSION)"QuickControls2 Qt"$(QT_MAJOR_VERSION)"Widgets Qt"$(QT_MAJOR_VERSION)"Svg Qt"$(QT_MAJOR_VERSION)"Multimedia Qt"$(QT_MAJOR_VERSION)"WebView Qt"$(QT_MAJOR_VERSION)"WebChannel)" + NIM_PARAMS += --passL:"$(DOTHERSIDE_LIBFILE)" --passL:"$(shell PKG_CONFIG_PATH="$(QT_PCFILEDIR)" $(PKG_CONFIG) --libs Qt"$(QT_MAJOR_VERSION)"Core Qt"$(QT_MAJOR_VERSION)"Qml Qt"$(QT_MAJOR_VERSION)"Gui Qt"$(QT_MAJOR_VERSION)"Quick Qt"$(QT_MAJOR_VERSION)"QuickControls2 Qt"$(QT_MAJOR_VERSION)"Widgets Qt"$(QT_MAJOR_VERSION)"Svg Qt"$(QT_MAJOR_VERSION)"Multimedia Qt"$(QT_MAJOR_VERSION)"WebView Qt"$(QT_MAJOR_VERSION)"WebChannel)" + # seaqt locates Qt via pkg-config at nim-compile time (gorge); make sure the Qt + # .pc dir is searched first while preserving any pre-existing PKG_CONFIG_PATH. + export PKG_CONFIG_PATH := $(QT_PCFILEDIR):$(PKG_CONFIG_PATH) else NIM_EXTRA_PARAMS := --passL:"-lsetupapi -lhid" endif diff --git a/config.nims b/config.nims index 0940be9c46..65451a75b8 100644 --- a/config.nims +++ b/config.nims @@ -55,6 +55,12 @@ switch("define", "chronicles_runtime_filtering=on") switch("define", "chronicles_default_output_device=dynamic") switch("define", "chronicles_log_level=trace") +# Compatibility include path for the vendored (Qt 6.4-generated) nim-seaqt +# bindings: gen_qvariant.cpp does `#include `, a convenience +# header Qt removed after 6.4 (absent in 6.11+). seaqt_compat/ provides a shim of +# that name so the *generated code stays pristine* and still compiles on newer Qt. +switch("passC", "-I" & thisDir() & "/seaqt_compat") + switch("passC", "-fno-omit-frame-pointer") switch("passL", "-fno-omit-frame-pointer") # The compiler doth protest too much, methinks, about all these cases where it can't diff --git a/nim_status_client.nimble b/nim_status_client.nimble index f97ba92586..210b54c44f 100644 --- a/nim_status_client.nimble +++ b/nim_status_client.nimble @@ -9,5 +9,4 @@ bin = @["nim_status_client"] skipExt = @["nim"] # Deps - -requires "nim >= 1.0.0", " nimqml >= 0.7.0", "stint", "nimcrypto >= 0.4.11", "uuids >= 0.1.10" +requires "nim >= 1.0.0", "stint", "nimcrypto >= 0.4.11", "uuids >= 0.1.10" diff --git a/seaqt_compat/QVariantConstPointer b/seaqt_compat/QVariantConstPointer new file mode 100644 index 0000000000..b2fe93d12d --- /dev/null +++ b/seaqt_compat/QVariantConstPointer @@ -0,0 +1,17 @@ +#pragma once +// Compatibility shim for status-desktop's seaqt migration. +// +// The vendored nim-seaqt bindings were generated against Qt 6.4, whose +// generated gen_qvariant.cpp does `#include `. Qt removed +// that camelCase convenience forwarding header after 6.4 (absent in 6.11), so +// the unmodified generated code fails to compile against newer Qt. The class +// itself still exists and is pulled in via (already included just +// above that line in the generated file), so this shim only needs to satisfy +// the include — it forwards to to be self-sufficient regardless of +// include order. +// +// This lives outside the vendored submodule on purpose: the generated bindings +// stay pristine. The directory is placed on the C++ include path via config.nims +// (`-I .../seaqt_compat`). Remove once the bindings are regenerated for the +// target Qt version (which won't emit this include at all). +#include diff --git a/src/app/core/custom_urls/urls_manager.nim b/src/app/core/custom_urls/urls_manager.nim index d7f904cd66..79847c0e08 100644 --- a/src/app/core/custom_urls/urls_manager.nim +++ b/src/app/core/custom_urls/urls_manager.nim @@ -1,4 +1,5 @@ import nimqml, strutils, chronicles +import dotherside_ext import ../eventemitter import ../../global/app_signals diff --git a/src/app/core/main.nim b/src/app/core/main.nim index 251fdba669..c8926ee008 100644 --- a/src/app/core/main.nim +++ b/src/app/core/main.nim @@ -1,4 +1,5 @@ import nimqml +import dotherside_ext import eventemitter, ./tasks/threadpool, diff --git a/src/app/core/notifications/notifications_manager.nim b/src/app/core/notifications/notifications_manager.nim index 00eca13610..578731f896 100644 --- a/src/app/core/notifications/notifications_manager.nim +++ b/src/app/core/notifications/notifications_manager.nim @@ -1,4 +1,5 @@ import nimqml, json, chronicles +import dotherside_ext import ../../global/app_signals import ../../global/global_singleton diff --git a/src/app/core/tasks/qt.nim b/src/app/core/tasks/qt.nim index 22fe5dc66c..a13f6c9692 100644 --- a/src/app/core/tasks/qt.nim +++ b/src/app/core/tasks/qt.nim @@ -1,6 +1,8 @@ import # vendor libs nimqml, json_serialization +import dotherside_ext + import # status-desktop libs ./common, app/global/app_lifecycle diff --git a/src/app/global/global_singleton.nim b/src/app/global/global_singleton.nim index a3cd21695b..5ab9226fd2 100644 --- a/src/app/global/global_singleton.nim +++ b/src/app/global/global_singleton.nim @@ -1,4 +1,5 @@ import nimqml +import dotherside_ext import local_account_settings import local_account_sensitive_settings diff --git a/src/app/global/local_account_sensitive_settings.nim b/src/app/global/local_account_sensitive_settings.nim index 5c188f8774..3623e15f59 100644 --- a/src/app/global/local_account_sensitive_settings.nim +++ b/src/app/global/local_account_sensitive_settings.nim @@ -1,4 +1,5 @@ import nimqml, os, json, chronicles +import dotherside_ext import ../../constants diff --git a/src/app/global/local_account_settings.nim b/src/app/global/local_account_settings.nim index be726d2600..3fe4f662af 100644 --- a/src/app/global/local_account_settings.nim +++ b/src/app/global/local_account_settings.nim @@ -1,4 +1,5 @@ import nimqml, os +import dotherside_ext import ../../constants diff --git a/src/app/global/local_app_settings.nim b/src/app/global/local_app_settings.nim index c6a247c7fa..6d0bd4e8a4 100644 --- a/src/app/global/local_app_settings.nim +++ b/src/app/global/local_app_settings.nim @@ -1,4 +1,5 @@ import nimqml, strutils, os +import dotherside_ext import constants diff --git a/src/app/global/utils.nim b/src/app/global/utils.nim index 826e9efef2..8cd134fd8a 100644 --- a/src/app/global/utils.nim +++ b/src/app/global/utils.nim @@ -1,4 +1,5 @@ import nimqml +import dotherside_ext import std/[strformat, strutils, httpclient, os, uri], regex, stint import stew/byteutils import ./utils/qrcodegen diff --git a/src/app/modules/main/chat_section/chat_content/input_area/view.nim b/src/app/modules/main/chat_section/chat_content/input_area/view.nim index 62ed29fbc4..fb1ebb1c8f 100644 --- a/src/app/modules/main/chat_section/chat_content/input_area/view.nim +++ b/src/app/modules/main/chat_section/chat_content/input_area/view.nim @@ -1,4 +1,5 @@ import nimqml, sets +import dotherside_ext import ./io_interface import ./preserved_properties import ./urls_model diff --git a/src/app/modules/main/view.nim b/src/app/modules/main/view.nim index 3a714612fa..2d999c0f23 100644 --- a/src/app/modules/main/view.nim +++ b/src/app/modules/main/view.nim @@ -1,4 +1,5 @@ import nimqml, strutils +import dotherside_ext import app/global/global_singleton import app/modules/shared_models/section_model import app/modules/shared_models/section_item diff --git a/src/app/modules/main/wallet_section/send/module.nim b/src/app/modules/main/wallet_section/send/module.nim index 28105060e9..2727a571b4 100644 --- a/src/app/modules/main/wallet_section/send/module.nim +++ b/src/app/modules/main/wallet_section/send/module.nim @@ -1,4 +1,5 @@ import tables, nimqml, sequtils, sugar, stint, strutils, chronicles +import dotherside_ext import ./io_interface, ./view, ./controller, ./network_route_item, ./transaction_routes, ./suggested_route_item, ./suggested_route_model, ./gas_estimate_item, ./gas_fees_item, ./network_route_model import ../io_interface as delegate_interface diff --git a/src/app/modules/main/wallet_section/send/view.nim b/src/app/modules/main/wallet_section/send/view.nim index 03df187b1d..20846b57d4 100644 --- a/src/app/modules/main/wallet_section/send/view.nim +++ b/src/app/modules/main/wallet_section/send/view.nim @@ -1,4 +1,5 @@ import nimqml, tables, json, sequtils, strutils, stint, chronicles +import dotherside_ext import ./io_interface, ./network_route_model, ./network_route_item, ./suggested_route_item, ./transaction_routes import app_service/service/network/service as network_service diff --git a/src/app/modules/shared_modules/add_account/view.nim b/src/app/modules/shared_modules/add_account/view.nim index 4a522f8abe..9328566bee 100644 --- a/src/app/modules/shared_modules/add_account/view.nim +++ b/src/app/modules/shared_modules/add_account/view.nim @@ -1,4 +1,5 @@ import nimqml +import dotherside_ext import io_interface import internal/[state, state_wrapper] import ../../shared_models/[keypair_model, keypair_item, derived_address_model] diff --git a/src/app/modules/shared_modules/collectibles/controller.nim b/src/app/modules/shared_modules/collectibles/controller.nim index 7d792f79a5..b18f647525 100644 --- a/src/app/modules/shared_modules/collectibles/controller.nim +++ b/src/app/modules/shared_modules/collectibles/controller.nim @@ -1,4 +1,5 @@ import nimqml, std/json, sequtils, sugar, strutils +import dotherside_ext import stint, chronicles, tables import app/modules/shared_models/collectibles_entry diff --git a/src/app/modules/shared_modules/keypair_import/view.nim b/src/app/modules/shared_modules/keypair_import/view.nim index f6aeb3397a..b293e424ff 100644 --- a/src/app/modules/shared_modules/keypair_import/view.nim +++ b/src/app/modules/shared_modules/keypair_import/view.nim @@ -1,4 +1,5 @@ import nimqml +import dotherside_ext import io_interface import internal/[state, state_wrapper] import app/modules/shared_models/[keypair_model, derived_address_model] diff --git a/src/app_service/service/chat/service.nim b/src/app_service/service/chat/service.nim index 769a93c50d..85aeb3483e 100644 --- a/src/app_service/service/chat/service.nim +++ b/src/app_service/service/chat/service.nim @@ -1,4 +1,5 @@ import nimqml, tables, json, sequtils, chronicles, os, strutils, uuids, base64 +import dotherside_ext import std/[times, os] import app/core/tasks/[qt, threadpool] diff --git a/src/app_service/service/community_tokens/service.nim b/src/app_service/service/community_tokens/service.nim index 45caca3d65..ce0bd62418 100644 --- a/src/app_service/service/community_tokens/service.nim +++ b/src/app_service/service/community_tokens/service.nim @@ -1,4 +1,5 @@ import nimqml, tables, chronicles, json, stint, strutils, sugar, sequtils, std/strformat, times +import dotherside_ext import app/global/global_singleton import app/core/eventemitter diff --git a/src/app_service/service/contacts/service.nim b/src/app_service/service/contacts/service.nim index 94b32ac1c5..91597c52b1 100644 --- a/src/app_service/service/contacts/service.nim +++ b/src/app_service/service/contacts/service.nim @@ -1,4 +1,5 @@ import nimqml, tables, json, sequtils, std/strformat, chronicles, strutils, times, std/times +import dotherside_ext import app/global/global_singleton import app/core/signals/types diff --git a/src/app_service/service/message/service.nim b/src/app_service/service/message/service.nim index 6effe5ae5f..d6cc366258 100644 --- a/src/app_service/service/message/service.nim +++ b/src/app_service/service/message/service.nim @@ -1,4 +1,5 @@ import nimqml, tables, json, regex, sequtils, std/strformat, strutils, chronicles, times, oids, uuids +import dotherside_ext import ../../../app/core/tasks/[qt, threadpool] import ../../../app/core/signals/types diff --git a/src/dotherside_ext.nim b/src/dotherside_ext.nim new file mode 100644 index 0000000000..ec77cc9cfd --- /dev/null +++ b/src/dotherside_ext.nim @@ -0,0 +1,274 @@ +## DOtherSide wrapper for status-desktop. +## +## The binding layer migrated from the status-im `nimqml` fork to `nimqml-seaqt`. +## nimqml-seaqt provides the standard QObject/QML machinery (backed by seaqt's +## `notherside`, `nos_*` symbols). DOtherSide is kept building as a *utility* +## static library (`vendor/DOtherSide`) and this module declares the subset of its +## `dos_*` C API we still use plus the thin high-level procs/types on top — ported +## verbatim from the old fork's `dotherside.nim` + `status/*` + `qsettings/qtimer` +## modules. +## +## DOtherSide's `dos_*` and notherside's `nos_*` C symbols don't overlap, so the +## two coexist in one binary. We never call DOtherSide's app/QObject-creation +## entry points (nimqml-seaqt creates those), only its leaf utility functions, so +## its heavy machinery stays dormant. The QObject pointers handed to `dos_*` come +## from nimqml-seaqt QObjects (real `QObject*` via the `vptr` accessors added to +## nimqml-seaqt for this migration). +## +## TODO: remove this and migrate to seaqt APIs or StatusQ + +import nimqml + +# DOtherSide library name. `--dynlibOverrideAll` (config.nims, macOS/Linux) makes +# these statically linked against libDOtherSideStatic.a; on Windows the DLL loads. +const dynLibName = + when defined(windows): "DOtherSide.dll" + elif defined(macosx): "libDOtherSide.dylib" + else: "libDOtherSide.so.0.(9|8)" + +type + DosMessageHandler* = proc(messageType: cint, message: cstring, category: cstring, + file: cstring, function: cstring, line: cint) {.cdecl.} + + QSettingsFormat* {.pure.} = enum + NativeFormat = 0 + IniFormat + + # Custom QObjects (real QObjects created by DOtherSide; adopted as nimqml-seaqt + # QObject subtypes so `newQVariant`/`signalConnect` work on them). + SingleInstance* = ref object of QObject + StatusEvent* = ref object of QObject + StatusOSNotification* = ref object of QObject + + # Qt classes nimqml-seaqt does not provide. + QSettings* = ref object of QObject + QTimer* = ref object of QObject + QNetworkAccessManagerFactory* = ref object of RootObj + vptr: pointer + +# --- DOtherSide C API (only what status still uses) -------------------------- +# QObject pointers are passed as raw `pointer` (a real C++ `QObject*`). +proc dos_chararray_delete(str: cstring) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_signal(vptr: pointer, signal: cstring, slot: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qobject_connect_static(sender: pointer, senderFunc: cstring, receiver: pointer, + receiverFunc: cstring, connectionType: cint): pointer {.cdecl, dynlib: dynLibName, importc.} + +proc dos_plain_text(htmlString: cstring): cstring {.cdecl, dynlib: dynLibName, importc.} +proc dos_escape_html(input: cstring): cstring {.cdecl, dynlib: dynLibName, importc.} +proc dos_save_byte_image_to_file(imagePath: cstring): cstring {.cdecl, dynlib: dynLibName, importc.} + +proc dos_app_is_active(engine: pointer): bool {.cdecl, dynlib: dynLibName, importc.} +proc dos_app_make_it_active(engine: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_add_self_signed_certificate(content: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_installMessageHandler(handler: DosMessageHandler) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qguiapplication_enable_hdpi(uiScaleFilePath: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtwebview_initialize() {.cdecl, dynlib: dynLibName, importc.} +proc dos_qguiapplication_try_enable_threaded_renderer() {.cdecl, dynlib: dynLibName, importc.} +proc dos_qguiapplication_installEventFilter(filter: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qguiapplication_exit() {.cdecl, dynlib: dynLibName, importc.} +proc dos_qguiapplication_icon(filename: cstring) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_qqmlnetworkaccessmanagerfactory_create(tmpPath: cstring): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_qqmlapplicationengine_setNetworkAccessManagerFactory(engine: pointer, factory: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_osnotification_create(): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_osnotification_show_notification(vptr: pointer, title, message, identifier: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_osnotification_show_badge_notification(vptr: pointer, notificationsCount: int) {.cdecl, dynlib: dynLibName, importc.} +proc dos_osnotification_delete(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_event_create_urlSchemeEvent(): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_event_delete(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_event_set_urlSchemeEvent_instance(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_singleinstance_create(uniqueName: cstring, eventStr: cstring): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_singleinstance_isfirst(vptr: pointer): bool {.cdecl, dynlib: dynLibName, importc.} +proc dos_singleinstance_delete(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_qsettings_create(fileName: cstring, format: int): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_value(vptr: pointer, key: cstring, defaultValue: pointer): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_set_value(vptr: pointer, key: cstring, value: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_remove(vptr: pointer, key: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_delete(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_begin_group(vptr: pointer, group: cstring) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qsettings_end_group(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} + +proc dos_qtimer_create(): pointer {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_delete(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_set_interval(vptr: pointer, interval: int) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_interval(vptr: pointer): int {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_start(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_stop(vptr: pointer) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_set_single_shot(vptr: pointer, singleShot: bool) {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_is_single_shot(vptr: pointer): bool {.cdecl, dynlib: dynLibName, importc.} +proc dos_qtimer_is_active(vptr: pointer): bool {.cdecl, dynlib: dynLibName, importc.} + +# --- High-level API (ported verbatim from the old nimqml fork) --------------- + +proc signal_handler*(receiver: pointer, signal: cstring, slot: cstring) = + if not receiver.isNil: + dos_signal(receiver, signal, slot) + +proc plain_text*(htmlString: string): string = + let s = dos_plain_text(htmlString.cstring) + defer: dos_chararray_delete(s) + result = $s + +proc escape_html*(input: string): string = + let s = dos_escape_html(input.cstring) + defer: dos_chararray_delete(s) + result = $s + +proc save_byte_image_to_file*(imagePath: string): string = + let s = dos_save_byte_image_to_file(imagePath.cstring) + defer: dos_chararray_delete(s) + result = $s + +proc app_isActive*(engine: QQmlApplicationEngine): bool = + dos_app_is_active(engine.vptr) + +proc app_makeItActive*(engine: QQmlApplicationEngine) = + dos_app_make_it_active(engine.vptr) + +proc signalConnect*(sender: QObject, signal: string, receiver: QObject, slot: string, + signalType: int = 0) = + discard dos_qobject_connect_static(sender.vptr, ("2" & signal).cstring, receiver.vptr, + ("1" & slot).cstring, signalType.cint) + +# QGuiApplication extras +proc installSelfSignedCertificate*(certificate: string) = + dos_add_self_signed_certificate(certificate.cstring) + +proc installMessageHandler*(handler: DosMessageHandler) = + dos_installMessageHandler(handler) + +proc enableHDPI*(uiScaleFilePath: string) = + dos_qguiapplication_enable_hdpi(uiScaleFilePath.cstring) + +proc initializeWebView*() = + dos_qtwebview_initialize() + +proc tryEnableThreadedRenderer*() = + dos_qguiapplication_try_enable_threaded_renderer() + +proc installEventFilter*(application: QGuiApplication, event: StatusEvent) = + dos_qguiapplication_installEventFilter(event.vptr) + +# nimqml-seaqt wraps `quit` but not `exit`/`icon`. DOtherSide's impls act on the +# global qApp (== the seaqt-created application), so they are safe here. +proc exit*(self: QGuiApplication) = + dos_qguiapplication_exit() + +proc icon*(application: QGuiApplication, filename: string) = + dos_qguiapplication_icon(filename.cstring) + +# QNetworkAccessManagerFactory (custom disk-cache factory) +proc delete*(self: QNetworkAccessManagerFactory) = + self.vptr = nil + +proc newQNetworkAccessManagerFactory*(tmpPath: string): QNetworkAccessManagerFactory = + new(result, delete) + result.vptr = dos_qqmlnetworkaccessmanagerfactory_create(tmpPath.cstring) + +proc setNetworkAccessManagerFactory*(self: QQmlApplicationEngine, + factory: QNetworkAccessManagerFactory) = + dos_qqmlapplicationengine_setNetworkAccessManagerFactory(self.vptr, factory.vptr) + +# OSNotification +proc delete*(self: StatusOSNotification) = + dos_osnotification_delete(self.vptr) + self.vptr = nil + +proc newStatusOSNotification*(): StatusOSNotification = + new(result, delete) + result.vptr = dos_osnotification_create() + +proc showNotification*(self: StatusOSNotification, title: string, message: string, + identifier: string) = + dos_osnotification_show_notification(self.vptr, title.cstring, message.cstring, + identifier.cstring) + +proc showIconBadgeNotification*(self: StatusOSNotification, notificationsCount: int) = + dos_osnotification_show_badge_notification(self.vptr, notificationsCount) + +# UrlSchemeEvent (deep links) +proc delete*(self: StatusEvent) = + dos_event_delete(self.vptr) + self.vptr = nil + +proc setInstance*(self: StatusEvent) = + dos_event_set_urlSchemeEvent_instance(self.vptr) + +proc newStatusUrlSchemeEventObject*(): StatusEvent = + new(result, delete) + result.vptr = dos_event_create_urlSchemeEvent() + +# SingleInstance +proc delete*(self: SingleInstance) = + if self.vptr.isNil: + return + dos_singleinstance_delete(self.vptr) + self.vptr = nil + +proc newSingleInstance*(uniqueName: string, eventStr: string): SingleInstance = + new(result, delete) + result.vptr = dos_singleinstance_create(uniqueName.cstring, eventStr.cstring) + +proc secondInstance*(self: SingleInstance): bool = + not dos_singleinstance_isfirst(self.vptr) + +# QSettings +proc delete*(self: QSettings) = + dos_qsettings_delete(self.vptr) + self.vptr = nil + +proc newQSettings*(fileName: string, + format: QSettingsFormat = QSettingsFormat.NativeFormat): QSettings = + new(result, delete) + result.vptr = dos_qsettings_create(fileName.cstring, format.int) + +proc value*(self: QSettings, key: string, defaultValue: QVariant = newQVariant()): QVariant = + newQVariantTakingPtr(dos_qsettings_value(self.vptr, key.cstring, defaultValue.vptr)) + +proc setValue*(self: QSettings, key: string, value: QVariant) = + dos_qsettings_set_value(self.vptr, key.cstring, value.vptr) + +proc remove*(self: QSettings, key: string) = + dos_qsettings_remove(self.vptr, key.cstring) + +proc beginGroup*(self: QSettings, group: string) = + dos_qsettings_begin_group(self.vptr, group.cstring) + +proc endGroup*(self: QSettings) = + dos_qsettings_end_group(self.vptr) + +# QTimer +proc delete*(self: QTimer) = + dos_qtimer_delete(self.vptr) + self.vptr = nil + +proc newQTimer*(): QTimer = + new(result, delete) + result.vptr = dos_qtimer_create() + +proc setInterval*(self: QTimer, interval: int) = + dos_qtimer_set_interval(self.vptr, interval) + +proc interval*(self: QTimer): int = + dos_qtimer_interval(self.vptr) + +proc start*(self: QTimer) = + dos_qtimer_start(self.vptr) + +proc stop*(self: QTimer) = + dos_qtimer_stop(self.vptr) + +proc setSingleShot*(self: QTimer, singleShot: bool) = + dos_qtimer_set_single_shot(self.vptr, singleShot) + +proc isSingleShot*(self: QTimer): bool = + dos_qtimer_is_single_shot(self.vptr) + +proc isActive*(self: QTimer): bool = + dos_qtimer_is_active(self.vptr) diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index 5ab0bc16b4..ffd0c76570 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -9,6 +9,7 @@ import status_go import app/core/main import constants as main_constants import statusq_bridge +import dotherside_ext import app/global/global_singleton import app/global/local_app_settings diff --git a/vendor/nim-seaqt b/vendor/nim-seaqt new file mode 160000 index 0000000000..2d95808bdd --- /dev/null +++ b/vendor/nim-seaqt @@ -0,0 +1 @@ +Subproject commit 2d95808bdd9f6dd2c212b69a57af4618da241d37 diff --git a/vendor/nimqml b/vendor/nimqml deleted file mode 160000 index e532812bef..0000000000 --- a/vendor/nimqml +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e532812bef92452dea2600e3ea6233819bd0e425 diff --git a/vendor/nimqml-seaqt b/vendor/nimqml-seaqt new file mode 160000 index 0000000000..a9e7303d65 --- /dev/null +++ b/vendor/nimqml-seaqt @@ -0,0 +1 @@ +Subproject commit a9e7303d657d5d82ac97464433312b88bb798dd3