feat: base_cpp
This commit is contained in:
parent
ad7f48d6ac
commit
4183069a9f
|
@ -0,0 +1,128 @@
|
||||||
|
# Checkout config tool: https://zed0.co.uk/clang-format-configurator/
|
||||||
|
# Or http://cf.monofraps.net/
|
||||||
|
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
|
# https://github.com/01org/parameter-framework/blob/master/.clang-format
|
||||||
|
|
||||||
|
# Tested on: clang-format version 6.0.1
|
||||||
|
|
||||||
|
|
||||||
|
# Common settings
|
||||||
|
BasedOnStyle: WebKit
|
||||||
|
TabWidth: 4
|
||||||
|
IndentWidth: 4
|
||||||
|
UseTab: Always
|
||||||
|
ColumnLimit: 120
|
||||||
|
|
||||||
|
# Other languages JavaScript, Proto
|
||||||
|
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
# http://releases.llvm.org/6.0.1/tools/clang/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code
|
||||||
|
# int formatted_code;
|
||||||
|
# // clang-format off
|
||||||
|
# void unformatted_code ;
|
||||||
|
# // clang-format on
|
||||||
|
# void formatted_code_again;
|
||||||
|
|
||||||
|
DisableFormat: false
|
||||||
|
Standard: Cpp11
|
||||||
|
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: true
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlinesLeft: false
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
|
||||||
|
# Configure each individual brace in BraceWrapping
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
# Control of individual brace wrapping cases
|
||||||
|
BraceWrapping: {
|
||||||
|
AfterClass: 'true'
|
||||||
|
AfterControlStatement: 'true'
|
||||||
|
AfterEnum : 'true'
|
||||||
|
AfterFunction : 'true'
|
||||||
|
AfterNamespace : 'true'
|
||||||
|
AfterStruct : 'true'
|
||||||
|
AfterUnion : 'true'
|
||||||
|
BeforeCatch : 'true'
|
||||||
|
BeforeElse : 'true'
|
||||||
|
IndentBraces : 'false'
|
||||||
|
AfterExternBlock : 'true'
|
||||||
|
SplitEmptyFunction : 'false'
|
||||||
|
SplitEmptyRecord : 'false'
|
||||||
|
SplitEmptyNamespace : 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakAfterJavaFieldAnnotations: true
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: true
|
||||||
|
BreakStringLiterals: true
|
||||||
|
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||||
|
IndentCaseLabels: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
JavaScriptQuotes: Double
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
ObjCSpaceAfterProperty: true
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Left
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: Never
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SortIncludes: true
|
||||||
|
|
||||||
|
# Comments are for developers, they should arrange them
|
||||||
|
ReflowComments: false
|
||||||
|
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IndentPPDirectives: AfterHash
|
|
@ -32,3 +32,56 @@ status-react-translations/
|
||||||
notarization.log
|
notarization.log
|
||||||
status-desktop.log
|
status-desktop.log
|
||||||
nim_status_client.log
|
nim_status_client.log
|
||||||
|
|
||||||
|
|
||||||
|
# CPP app =====================================================================
|
||||||
|
|
||||||
|
|
||||||
|
# https://github.com/github/gitignore/blob/master/CMake.gitignore
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
|
project(status-desktop
|
||||||
|
VERSION 0.1.0
|
||||||
|
LANGUAGES CXX)
|
||||||
|
|
||||||
|
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Started CMake for ${PROJECT_NAME} v${PROJECT_VERSION}...\n")
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
|
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
|
||||||
|
# Check https://doc.qt.io/qt/deployment-android.html for more information.
|
||||||
|
# They need to be set before the find_package(...) calls below.
|
||||||
|
|
||||||
|
#if(ANDROID)
|
||||||
|
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||||
|
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
|
||||||
|
# set(ANDROID_EXTRA_LIBS
|
||||||
|
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
|
||||||
|
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
|
||||||
|
# endif()
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick Widgets Concurrent REQUIRED)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick Widgets Concurrent REQUIRED)
|
||||||
|
|
||||||
|
set(PROJECT_SOURCES
|
||||||
|
src-cpp/main.cpp
|
||||||
|
src-cpp/constants.cpp
|
||||||
|
src-cpp/logs.cpp
|
||||||
|
resources.rcc
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
|
qt_add_executable(status-desktop
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
if(ANDROID)
|
||||||
|
add_library(status-desktop SHARED
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
add_executable(status-desktop
|
||||||
|
${PROJECT_SOURCES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/vendor/status-lib/vendor/status-go bin/status-go)
|
||||||
|
|
||||||
|
# The following are dependencies that do not include CMakeList.txt files
|
||||||
|
# Create a PR in those projects so we can include them just like it was
|
||||||
|
# done with status-go
|
||||||
|
include(cmake/QRCodeGen.cmake)
|
||||||
|
include(cmake/Keycard.cmake)
|
||||||
|
|
||||||
|
# Submodiles
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src-cpp/dotherside)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src-cpp/app)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src-cpp/app_service)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src-cpp/backend)
|
||||||
|
|
||||||
|
target_include_directories(status-desktop PUBLIC include)
|
||||||
|
|
||||||
|
|
||||||
|
target_compile_definitions(status-desktop
|
||||||
|
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
||||||
|
|
||||||
|
target_link_libraries(status-desktop
|
||||||
|
PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
|
DOtherSide
|
||||||
|
statusgo_shared # <- Link status-go with this target (remove `_shared` for static linking)
|
||||||
|
qrcodegen
|
||||||
|
keycard
|
||||||
|
app_service
|
||||||
|
app
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_custom_target(rcc ALL DEPENDS resources.rcc)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT resources.rcc
|
||||||
|
COMMENT "Building resources.rcc"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -f ${CMAKE_CURRENT_SOURCE_DIR}/resources.rcc
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -f ${CMAKE_CURRENT_SOURCE_DIR}/ui/resources.qrc
|
||||||
|
COMMAND go run ${CMAKE_CURRENT_SOURCE_DIR}/ui/generate-rcc.go -source=${CMAKE_CURRENT_SOURCE_DIR}/ui -output=${CMAKE_CURRENT_SOURCE_DIR}/ui/resources.qrc
|
||||||
|
COMMAND rcc -binary $<$<CONFIG:Debug>:--no-compress> ${CMAKE_CURRENT_SOURCE_DIR}/ui/resources.qrc ${CMAKE_CURRENT_SOURCE_DIR}/resources/resources.qrc -o ${CMAKE_CURRENT_SOURCE_DIR}/resources.rcc
|
||||||
|
VERBATIM
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# run
|
||||||
|
add_custom_target(run
|
||||||
|
COMMENT "Execute desktop"
|
||||||
|
DEPENDS status-desktop
|
||||||
|
COMMAND ./status-desktop
|
||||||
|
VERBATIM
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# run debug
|
||||||
|
add_custom_target(run-debug
|
||||||
|
COMMENT "Execute desktop with debugger on port 1234"
|
||||||
|
DEPENDS status-desktop
|
||||||
|
COMMAND ./status-desktop -qmljsdebugger=port:1234
|
||||||
|
VERBATIM
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
12
README.md
12
README.md
|
@ -6,3 +6,15 @@ Desktop client for the [Status Network](https://statusnetwork.com/) built with [
|
||||||
|
|
||||||
Dev Docs: [https://hackmd.io/@status-desktop/B1naRjxh_/https%3A%2F%2Fhackmd.io%2F%40status-desktop%2FB1eOaf-nd](https://hackmd.io/@status-desktop/B1naRjxh_/https%3A%2F%2Fhackmd.io%2F%40status-desktop%2FB1eOaf-nd)
|
Dev Docs: [https://hackmd.io/@status-desktop/B1naRjxh_/https%3A%2F%2Fhackmd.io%2F%40status-desktop%2FB1eOaf-nd](https://hackmd.io/@status-desktop/B1naRjxh_/https%3A%2F%2Fhackmd.io%2F%40status-desktop%2FB1eOaf-nd)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# CPP app
|
||||||
|
|
||||||
|
```
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
./test-qtapp
|
||||||
|
```
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Keycard
|
||||||
|
# TODO: create a PR in that project to build it like we do with status-go ^
|
||||||
|
set(KEYCARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/vendor/status-lib/vendor/nim-keycard-go)
|
||||||
|
set(KEYCARD_LIB_DIR ${KEYCARD_ROOT}/go/keycard/build/libkeycard)
|
||||||
|
ExternalProject_Add(libkeycard
|
||||||
|
PREFIX ${KEYCARD_ROOT}
|
||||||
|
SOURCE_DIR ${KEYCARD_ROOT}
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
BUILD_COMMAND make build-keycard-go V=1
|
||||||
|
BUILD_BYPRODUCTS ${KEYCARD_LIB_DIR}/libkeycard${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||||
|
)
|
||||||
|
ExternalProject_Get_Property(libkeycard SOURCE_DIR)
|
||||||
|
add_library(keycard SHARED IMPORTED)
|
||||||
|
set_property(TARGET keycard PROPERTY IMPORTED_LOCATION ${KEYCARD_LIB_DIR}/libkeycard${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||||
|
add_dependencies(keycard libkeycard)
|
||||||
|
include_directories(${KEYCARD_LIB_DIR})
|
|
@ -0,0 +1,20 @@
|
||||||
|
# QR-Code-generator
|
||||||
|
# TODO: create a PR in that project to build it like we do with status-go ^
|
||||||
|
set(QRCODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/vendor/QR-Code-generator)
|
||||||
|
set(QRCODE_LIB_DIR ${QRCODE_ROOT}/cpp)
|
||||||
|
ExternalProject_Add(libqrcodegen
|
||||||
|
PREFIX ${QRCODE_ROOT}
|
||||||
|
SOURCE_DIR ${QRCODE_ROOT}
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
BUILD_IN_SOURCE 1
|
||||||
|
BUILD_COMMAND make -C cpp libqrcodegen.a V=1
|
||||||
|
BUILD_BYPRODUCTS ${QRCODE_LIB_DIR}/libqrcodegen.a
|
||||||
|
)
|
||||||
|
ExternalProject_Get_Property(libqrcodegen SOURCE_DIR)
|
||||||
|
add_library(qrcodegen STATIC IMPORTED)
|
||||||
|
set_property(TARGET qrcodegen PROPERTY IMPORTED_LOCATION ${QRCODE_LIB_DIR}/libqrcodegen.a)
|
||||||
|
add_dependencies(qrcodegen libqrcodegen)
|
||||||
|
include_directories(${QRCODE_LIB_DIR})
|
|
@ -1,53 +0,0 @@
|
||||||
|
|
||||||
# https://github.com/github/gitignore/blob/master/CMake.gitignore
|
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
CMakeLists.txt.user
|
|
||||||
CMakeCache.txt
|
|
||||||
CMakeFiles
|
|
||||||
CMakeScripts
|
|
||||||
Testing
|
|
||||||
Makefile
|
|
||||||
cmake_install.cmake
|
|
||||||
install_manifest.txt
|
|
||||||
compile_commands.json
|
|
||||||
CTestTestfile.cmake
|
|
||||||
_deps
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# https://github.com/github/gitignore/blob/master/C%2B%2B.gitignore
|
|
||||||
# ==============================================================================
|
|
||||||
|
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
|
@ -1,63 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.14)
|
|
||||||
|
|
||||||
project(test-qtapp LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
set(CMAKE_AUTORCC ON)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
include(ExternalProject)
|
|
||||||
|
|
||||||
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
|
|
||||||
# Check https://doc.qt.io/qt/deployment-android.html for more information.
|
|
||||||
# They need to be set before the find_package(...) calls below.
|
|
||||||
|
|
||||||
#if(ANDROID)
|
|
||||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
|
||||||
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
|
|
||||||
# set(ANDROID_EXTRA_LIBS
|
|
||||||
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
|
|
||||||
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
|
|
||||||
# endif()
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED)
|
|
||||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED)
|
|
||||||
|
|
||||||
set(PROJECT_SOURCES
|
|
||||||
main.cpp
|
|
||||||
qml.qrc
|
|
||||||
)
|
|
||||||
|
|
||||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
|
||||||
qt_add_executable(test-qtapp
|
|
||||||
${PROJECT_SOURCES}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
if(ANDROID)
|
|
||||||
add_library(test-qtapp SHARED
|
|
||||||
${PROJECT_SOURCES}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_executable(test-qtapp
|
|
||||||
${PROJECT_SOURCES}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# status-go has a CMakeLists.txt file we can use
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/status-lib/vendor/status-go bin/status-go)
|
|
||||||
|
|
||||||
target_compile_definitions(test-qtapp
|
|
||||||
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
|
||||||
|
|
||||||
target_link_libraries(test-qtapp
|
|
||||||
PRIVATE
|
|
||||||
Qt${QT_VERSION_MAJOR}::Core
|
|
||||||
Qt${QT_VERSION_MAJOR}::Quick
|
|
||||||
statusgo_shared) # <- Link status-go with this target (remove `_shared` for static linking)
|
|
|
@ -1,11 +0,0 @@
|
||||||
# Example QT app
|
|
||||||
|
|
||||||
```
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make
|
|
||||||
./test-qtapp
|
|
||||||
```
|
|
||||||
|
|
||||||
This example app just shows how to plug-in status-go in a qt-app.
|
|
||||||
Also check [status-cpp](https://github.com/richard-ramos/status-cpp)
|
|
|
@ -1,48 +0,0 @@
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QQmlApplicationEngine>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "libstatus.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
|
|
||||||
QString hello = "Hello World!";
|
|
||||||
const char* result = HashMessage(hello.toUtf8().data()); // <- HashMessage comes from libstatus.h
|
|
||||||
const auto response = QJsonDocument::fromJson(QString(result).toUtf8()).object(); // <- For now, status-go always returns json
|
|
||||||
if (!response["error"].isUndefined() || !response["error"].toString().isEmpty()){ // <- Always do error handling
|
|
||||||
std::cout << "Could not obtain hash: " << response["result"].toString().toStdString() << std::endl << std::flush;
|
|
||||||
} else {
|
|
||||||
std::cout << "Hash of HelloWorld: " << response["result"].toString().toStdString() << std::endl << std::flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For handling signals, see:
|
|
||||||
// https://github.com/richard-ramos/status-cpp/blob/master/src/core/status.cpp#L36
|
|
||||||
// https://github.com/richard-ramos/status-cpp/blob/master/src/core/status.cpp#L124-L127
|
|
||||||
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
|
||||||
const QUrl url(QStringLiteral("qrc:/main.qml"));
|
|
||||||
QObject::connect(
|
|
||||||
&engine, &QQmlApplicationEngine::objectCreated,
|
|
||||||
&app, [url](QObject *obj, const QUrl &objUrl)
|
|
||||||
{
|
|
||||||
if (!obj && url == objUrl)
|
|
||||||
QCoreApplication::exit(-1);
|
|
||||||
},
|
|
||||||
Qt::QueuedConnection);
|
|
||||||
engine.load(url);
|
|
||||||
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import QtQuick 2.14
|
|
||||||
import QtQuick.Window 2.14
|
|
||||||
|
|
||||||
Window {
|
|
||||||
width: 640
|
|
||||||
height: 480
|
|
||||||
visible: true
|
|
||||||
title: qsTr("Hello World")
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>main.qml</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "testnet_rpc",
|
||||||
|
"etherscan-link": "https://ropsten.etherscan.io/address/",
|
||||||
|
"name": "Ropsten with upstream RPC",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 3,
|
||||||
|
"DataDir": "/ethereum/testnet_rpc",
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://ropsten.infura.io/v3/%INFURA_KEY%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rinkeby_rpc",
|
||||||
|
"etherscan-link": "https://rinkeby.etherscan.io/address/",
|
||||||
|
"name": "Rinkeby with upstream RPC",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 4,
|
||||||
|
"DataDir": "/ethereum/rinkeby_rpc",
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://rinkeby.infura.io/v3/%INFURA_KEY%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "goerli_rpc",
|
||||||
|
"etherscan-link": "https://goerli.etherscan.io/address/",
|
||||||
|
"name": "Goerli with upstream RPC",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 5,
|
||||||
|
"DataDir": "/ethereum/goerli_rpc",
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://goerli.blockscout.com/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mainnet_rpc",
|
||||||
|
"etherscan-link": "https://etherscan.io/address/",
|
||||||
|
"name": "Mainnet with upstream RPC",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 1,
|
||||||
|
"DataDir": "/ethereum/mainnet_rpc",
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://mainnet.infura.io/v3/%INFURA_KEY%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xdai_rpc",
|
||||||
|
"name": "xDai Chain",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 100,
|
||||||
|
"DataDir": "/ethereum/xdai_rpc",
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://dai.poa.network"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "poa_rpc",
|
||||||
|
"name": "POA Network",
|
||||||
|
"config": {
|
||||||
|
"NetworkId": 99,
|
||||||
|
"DataDir": "/ethereum/poa_rpc",
|
||||||
|
"UpstreamConfig": { "Enabled": true, "URL": "https://core.poa.network" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
{
|
||||||
|
"fleets": {
|
||||||
|
"eth.prod": {
|
||||||
|
"boot": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.prod": "enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443",
|
||||||
|
"boot-01.do-ams3.eth.prod": "enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443",
|
||||||
|
"boot-01.gc-us-central1-a.eth.prod": "enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443",
|
||||||
|
"boot-02.ac-cn-hongkong-c.eth.prod": "enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443",
|
||||||
|
"boot-02.do-ams3.eth.prod": "enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443",
|
||||||
|
"boot-02.gc-us-central1-a.eth.prod": "enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443"
|
||||||
|
},
|
||||||
|
"mail": {
|
||||||
|
"mail-01.ac-cn-hongkong-c.eth.prod": "enode://606ae04a71e5db868a722c77a21c8244ae38f1bd6e81687cc6cfe88a3063fa1c245692232f64f45bd5408fed5133eab8ed78049332b04f9c110eac7f71c1b429@47.75.247.214:443",
|
||||||
|
"mail-01.do-ams3.eth.prod": "enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@178.128.142.54:443",
|
||||||
|
"mail-01.gc-us-central1-a.eth.prod": "enode://ee2b53b0ace9692167a410514bca3024695dbf0e1a68e1dff9716da620efb195f04a4b9e873fb9b74ac84de801106c465b8e2b6c4f0d93b8749d1578bfcaf03e@104.197.238.144:443",
|
||||||
|
"mail-02.ac-cn-hongkong-c.eth.prod": "enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443",
|
||||||
|
"mail-02.do-ams3.eth.prod": "enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@178.128.142.26:443",
|
||||||
|
"mail-02.gc-us-central1-a.eth.prod": "enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443",
|
||||||
|
"mail-03.ac-cn-hongkong-c.eth.prod": "enode://e85f1d4209f2f99da801af18db8716e584a28ad0bdc47fbdcd8f26af74dbd97fc279144680553ec7cd9092afe683ddea1e0f9fc571ebcb4b1d857c03a088853d@47.244.129.82:443",
|
||||||
|
"mail-03.do-ams3.eth.prod": "enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@178.128.142.94:443",
|
||||||
|
"mail-03.gc-us-central1-a.eth.prod": "enode://44160e22e8b42bd32a06c1532165fa9e096eebedd7fa6d6e5f8bbef0440bc4a4591fe3651be68193a7ec029021cdb496cfe1d7f9f1dc69eb99226e6f39a7a5d4@35.225.221.245:443"
|
||||||
|
},
|
||||||
|
"rendezvous": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.prod": "/ip4/47.75.99.169/tcp/30703/ethv4/16Uiu2HAmV8Hq9e3zm9TMVP4zrVHo3BjqW5D6bDVV6VQntQd687e4",
|
||||||
|
"boot-01.do-ams3.eth.prod": "/ip4/178.128.138.128/tcp/30703/ethv4/16Uiu2HAmRHPzF3rQg55PgYPcQkyvPVH9n2hWsYPhUJBZ6kVjJgdV",
|
||||||
|
"boot-01.gc-us-central1-a.eth.prod": "/ip4/34.70.75.208/tcp/30703/ethv4/16Uiu2HAm6ZsERLx2BwVD2UM9SVPnnMU6NBycG8XPtu8qKys5awsU",
|
||||||
|
"boot-02.ac-cn-hongkong-c.eth.prod": "/ip4/47.52.106.107/tcp/30703/ethv4/16Uiu2HAmEHiptiDDd9gqNY8oQqo8hHUWMHJzfwt5aLRdD6W2zcXR",
|
||||||
|
"boot-02.do-ams3.eth.prod": "/ip4/178.128.140.188/tcp/30703/ethv4/16Uiu2HAmLqTXuY4Sb6G28HNooaFUXUKzpzKXCcgyJxgaEE2i5vnf",
|
||||||
|
"boot-02.gc-us-central1-a.eth.prod": "/ip4/35.223.215.156/tcp/30703/ethv4/16Uiu2HAmQEUFE2YaJohavWtHxPTEFv3sEGJtDqvtGEv78DFoEWQF"
|
||||||
|
},
|
||||||
|
"whisper": {
|
||||||
|
"node-01.ac-cn-hongkong-c.eth.prod": "enode://b957e51f41e4abab8382e1ea7229e88c6e18f34672694c6eae389eac22dab8655622bbd4a08192c321416b9becffaab11c8e2b7a5d0813b922aa128b82990dab@47.75.222.178:443",
|
||||||
|
"node-01.do-ams3.eth.prod": "enode://66ba15600cda86009689354c3a77bdf1a97f4f4fb3ab50ffe34dbc904fac561040496828397be18d9744c75881ffc6ac53729ddbd2cdbdadc5f45c400e2622f7@178.128.141.87:443",
|
||||||
|
"node-01.gc-us-central1-a.eth.prod": "enode://182ed5d658d1a1a4382c9e9f7c9e5d8d9fec9db4c71ae346b9e23e1a589116aeffb3342299bdd00e0ab98dbf804f7b2d8ae564ed18da9f45650b444aed79d509@34.68.132.118:443",
|
||||||
|
"node-02.ac-cn-hongkong-c.eth.prod": "enode://8bebe73ddf7cf09e77602c7d04c93a73f455b51f24ae0d572917a4792f1dec0bb4c562759b8830cc3615a658d38c1a4a38597a1d7ae3ba35111479fc42d65dec@47.75.85.212:443",
|
||||||
|
"node-02.do-ams3.eth.prod": "enode://4ea35352702027984a13274f241a56a47854a7fd4b3ba674a596cff917d3c825506431cf149f9f2312a293bb7c2b1cca55db742027090916d01529fe0729643b@134.209.136.79:443",
|
||||||
|
"node-02.gc-us-central1-a.eth.prod": "enode://fbeddac99d396b91d59f2c63a3cb5fc7e0f8a9f7ce6fe5f2eed5e787a0154161b7173a6a73124a4275ef338b8966dc70a611e9ae2192f0f2340395661fad81c0@34.67.230.193:443",
|
||||||
|
"node-03.ac-cn-hongkong-c.eth.prod": "enode://ac3948b2c0786ada7d17b80cf869cf59b1909ea3accd45944aae35bf864cc069126da8b82dfef4ddf23f1d6d6b44b1565c4cf81c8b98022253c6aea1a89d3ce2@47.75.88.12:443",
|
||||||
|
"node-03.do-ams3.eth.prod": "enode://ce559a37a9c344d7109bd4907802dd690008381d51f658c43056ec36ac043338bd92f1ac6043e645b64953b06f27202d679756a9c7cf62fdefa01b2e6ac5098e@134.209.136.123:443",
|
||||||
|
"node-03.gc-us-central1-a.eth.prod": "enode://c07aa0deea3b7056c5d45a85bca42f0d8d3b1404eeb9577610f386e0a4744a0e7b2845ae328efc4aa4b28075af838b59b5b3985bffddeec0090b3b7669abc1f3@35.226.92.155:443",
|
||||||
|
"node-04.ac-cn-hongkong-c.eth.prod": "enode://385579fc5b14e04d5b04af7eee835d426d3d40ccf11f99dbd95340405f37cf3bbbf830b3eb8f70924be0c2909790120682c9c3e791646e2d5413e7801545d353@47.244.221.249:443",
|
||||||
|
"node-04.do-ams3.eth.prod": "enode://4e0a8db9b73403c9339a2077e911851750fc955db1fc1e09f81a4a56725946884dd5e4d11258eac961f9078a393c45bcab78dd0e3bc74e37ce773b3471d2e29c@134.209.136.101:443",
|
||||||
|
"node-04.gc-us-central1-a.eth.prod": "enode://0624b4a90063923c5cc27d12624b6a49a86dfb3623fcb106801217fdbab95f7617b83fa2468b9ae3de593ff6c1cf556ccf9bc705bfae9cb4625999765127b423@35.222.158.246:443",
|
||||||
|
"node-05.ac-cn-hongkong-c.eth.prod": "enode://b77bffc29e2592f30180311dd81204ab845e5f78953b5ba0587c6631be9c0862963dea5eb64c90617cf0efd75308e22a42e30bc4eb3cd1bbddbd1da38ff6483e@47.75.10.177:443",
|
||||||
|
"node-05.do-ams3.eth.prod": "enode://a8bddfa24e1e92a82609b390766faa56cf7a5eef85b22a2b51e79b333c8aaeec84f7b4267e432edd1cf45b63a3ad0fc7d6c3a16f046aa6bc07ebe50e80b63b8c@178.128.141.249:443",
|
||||||
|
"node-05.gc-us-central1-a.eth.prod": "enode://a5fe9c82ad1ffb16ae60cb5d4ffe746b9de4c5fbf20911992b7dd651b1c08ba17dd2c0b27ee6b03162c52d92f219961cc3eb14286aca8a90b75cf425826c3bd8@104.154.230.58:443",
|
||||||
|
"node-06.ac-cn-hongkong-c.eth.prod": "enode://cf5f7a7e64e3b306d1bc16073fba45be3344cb6695b0b616ccc2da66ea35b9f35b3b231c6cf335fdfaba523519659a440752fc2e061d1e5bc4ef33864aac2f19@47.75.221.196:443",
|
||||||
|
"node-06.do-ams3.eth.prod": "enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@178.128.141.0:443",
|
||||||
|
"node-06.gc-us-central1-a.eth.prod": "enode://282e009967f9f132a5c2dd366a76319f0d22d60d0c51f7e99795a1e40f213c2705a2c10e4cc6f3890319f59da1a535b8835ed9b9c4b57c3aad342bf312fd7379@35.223.240.17:443",
|
||||||
|
"node-07.ac-cn-hongkong-c.eth.prod": "enode://13d63a1f85ccdcbd2fb6861b9bd9d03f94bdba973608951f7c36e5df5114c91de2b8194d71288f24bfd17908c48468e89dd8f0fb8ccc2b2dedae84acdf65f62a@47.244.210.80:443",
|
||||||
|
"node-07.do-ams3.eth.prod": "enode://2b01955d7e11e29dce07343b456e4e96c081760022d1652b1c4b641eaf320e3747871870fa682e9e9cfb85b819ce94ed2fee1ac458904d54fd0b97d33ba2c4a4@134.209.136.112:443",
|
||||||
|
"node-07.gc-us-central1-a.eth.prod": "enode://b706a60572634760f18a27dd407b2b3582f7e065110dae10e3998498f1ae3f29ba04db198460d83ed6d2bfb254bb06b29aab3c91415d75d3b869cd0037f3853c@35.239.5.162:443",
|
||||||
|
"node-08.ac-cn-hongkong-c.eth.prod": "enode://32915c8841faaef21a6b75ab6ed7c2b6f0790eb177ad0f4ea6d731bacc19b938624d220d937ebd95e0f6596b7232bbb672905ee12601747a12ee71a15bfdf31c@47.75.59.11:443",
|
||||||
|
"node-08.do-ams3.eth.prod": "enode://0d9d65fcd5592df33ed4507ce862b9c748b6dbd1ea3a1deb94e3750052760b4850aa527265bbaf357021d64d5cc53c02b410458e732fafc5b53f257944247760@178.128.141.42:443",
|
||||||
|
"node-08.gc-us-central1-a.eth.prod": "enode://e87f1d8093d304c3a9d6f1165b85d6b374f1c0cc907d39c0879eb67f0a39d779be7a85cbd52920b6f53a94da43099c58837034afa6a7be4b099bfcd79ad13999@35.238.106.101:443"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eth.staging": {
|
||||||
|
"boot": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.staging": "enode://630b0342ca4e9552f50714b6c8e28d6955bc0fd14e7950f93bc3b2b8cc8c1f3b6d103df66f51a13d773b5db0f130661fb5c7b8fa21c48890c64c79b41a56a490@47.91.229.44:443",
|
||||||
|
"boot-01.do-ams3.eth.staging": "enode://f79fb3919f72ca560ad0434dcc387abfe41e0666201ebdada8ede0462454a13deb05cda15f287d2c4bd85da81f0eb25d0a486bbbc8df427b971ac51533bd00fe@174.138.107.239:443",
|
||||||
|
"boot-01.gc-us-central1-a.eth.staging": "enode://10a78c17929a7019ef4aa2249d7302f76ae8a06f40b2dc88b7b31ebff4a623fbb44b4a627acba296c1ced3775d91fbe18463c15097a6a36fdb2c804ff3fc5b35@35.238.97.234:443"
|
||||||
|
},
|
||||||
|
"mail": {
|
||||||
|
"mail-01.ac-cn-hongkong-c.eth.staging": "enode://b74859176c9751d314aeeffc26ec9f866a412752e7ddec91b19018a18e7cca8d637cfe2cedcb972f8eb64d816fbd5b4e89c7e8c7fd7df8a1329fa43db80b0bfe@47.52.90.156:443",
|
||||||
|
"mail-01.do-ams3.eth.staging": "enode://69f72baa7f1722d111a8c9c68c39a31430e9d567695f6108f31ccb6cd8f0adff4991e7fdca8fa770e75bc8a511a87d24690cbc80e008175f40c157d6f6788d48@206.189.240.16:443",
|
||||||
|
"mail-01.gc-us-central1-a.eth.staging": "enode://e4fc10c1f65c8aed83ac26bc1bfb21a45cc1a8550a58077c8d2de2a0e0cd18e40fd40f7e6f7d02dc6cd06982b014ce88d6e468725ffe2c138e958788d0002a7f@35.239.193.41:443"
|
||||||
|
},
|
||||||
|
"rendezvous": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.staging": "/ip4/47.91.229.44/tcp/30703/ethv4/16Uiu2HAmRnt2Eyoknh3auxh4fJwkRgqkH1gqrWGes8Pk1k3MV4xu",
|
||||||
|
"boot-01.do-ams3.eth.staging": "/ip4/174.138.107.239/tcp/30703/ethv4/16Uiu2HAm8UZXUHEPZrpJbcQ3yVFH6UtKrwsG6jH4ai72PsbLfVFb",
|
||||||
|
"boot-01.gc-us-central1-a.eth.staging": "/ip4/35.238.97.234/tcp/30703/ethv4/16Uiu2HAm6G9sDMkrB4Xa5EH3Zx2dysCxFgBTSRzghic3Z9tRFRNE"
|
||||||
|
},
|
||||||
|
"whisper": {
|
||||||
|
"node-01.ac-cn-hongkong-c.eth.staging": "enode://088cf5a93c576fae52f6f075178467b8ff98bacf72f59e88efb16dfba5b30f80a4db78f8e3cb3d87f2f6521746ef4a8768465ef2896c6af24fd77a425e95b6dd@47.52.226.137:443",
|
||||||
|
"node-01.do-ams3.eth.staging": "enode://914c0b30f27bab30c1dfd31dad7652a46fda9370542aee1b062498b1345ee0913614b8b9e3e84622e84a7203c5858ae1d9819f63aece13ee668e4f6668063989@167.99.19.148:443",
|
||||||
|
"node-01.gc-us-central1-a.eth.staging": "enode://d3878441652f010326889f28360e69f2d09d06540f934fada0e17b374ce5319de64279aba3c44a5bf807d9967c6d705b3b4c6b03fa70763240e2ee6af01a539e@35.192.0.86:443"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eth.test": {
|
||||||
|
"boot": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.test": "enode://daae2e72820e86e942fa2a8aa7d6e9954d4043a753483d8bd338e16be82cf962392d5c0e1ae57c3d793c3d3dddd8fd58339262e4234dc966f953cd73b535f5fa@47.52.188.149:443",
|
||||||
|
"boot-01.do-ams3.eth.test": "enode://9e0988575eb7717c25dea72fd11c7b37767dc09c1a7686f7c2ec577d308d24b377ceb675de4317474a1a870e47882732967f4fa785b02ba95d669b31d464dec0@206.189.243.164:443",
|
||||||
|
"boot-01.gc-us-central1-a.eth.test": "enode://c1e5018887c863d64e431b69bf617561087825430e4401733f5ba77c70db14236df381fefb0ebe1ac42294b9e261bbe233dbdb83e32c586c66ae26c8de70cb4c@35.188.168.137:443"
|
||||||
|
},
|
||||||
|
"mail": {
|
||||||
|
"mail-01.ac-cn-hongkong-c.eth.test": "enode://619dbb5dda12e85bf0eb5db40fb3de625609043242737c0e975f7dfd659d85dc6d9a84f9461a728c5ab68c072fed38ca6a53917ca24b8e93cc27bdef3a1e79ac@47.52.188.196:443",
|
||||||
|
"mail-01.do-ams3.eth.test": "enode://e4865fe6c2a9c1a563a6447990d8e9ce672644ae3e08277ce38ec1f1b690eef6320c07a5d60c3b629f5d4494f93d6b86a745a0bf64ab295bbf6579017adc6ed8@206.189.243.161:443",
|
||||||
|
"mail-01.gc-us-central1-a.eth.test": "enode://707e57453acd3e488c44b9d0e17975371e2f8fb67525eae5baca9b9c8e06c86cde7c794a6c2e36203bf9f56cae8b0e50f3b33c4c2b694a7baeea1754464ce4e3@35.192.229.172:443"
|
||||||
|
},
|
||||||
|
"rendezvous": {
|
||||||
|
"boot-01.ac-cn-hongkong-c.eth.test": "/ip4/47.52.188.149/tcp/30703/ethv4/16Uiu2HAm9Vatqr4GfVCqnyeaPtCF3q8fz8kDDUgqXVfFG7ZfSA7w",
|
||||||
|
"boot-01.do-ams3.eth.test": "/ip4/206.189.243.164/tcp/30703/ethv4/16Uiu2HAmBCh5bgYr6V3fDuLqUzvtSAsFTQJCQ3TVHT8ta8bTu2Jm",
|
||||||
|
"boot-01.gc-us-central1-a.eth.test": "/ip4/35.188.168.137/tcp/30703/ethv4/16Uiu2HAm3MUqtGjmetyZ9L4SN2R8oHDWvACUcec25LjtDD5euiRH"
|
||||||
|
},
|
||||||
|
"whisper": {
|
||||||
|
"node-01.ac-cn-hongkong-c.eth.test": "enode://ad38f94030a846cc7005b7a1f3b6b01bf4ef59d34e8d3d6f4d12df23d14ba8656702a435d34cf4df3b412c0c1923df5adcce8461321a0d8ffb9435b26e572c2a@47.52.255.194:443",
|
||||||
|
"node-01.do-ams3.eth.test": "enode://1d193635e015918fb85bbaf774863d12f65d70c6977506187ef04420d74ec06c9e8f0dcb57ea042f85df87433dab17a1260ed8dde1bdf9d6d5d2de4b7bf8e993@206.189.243.163:443",
|
||||||
|
"node-01.gc-us-central1-a.eth.test": "enode://f593a27731bc0f8eb088e2d39222c2d59dfb9bf0b3950d7a828d51e8ab9e08fffbd9916a82fd993c1a080c57c2bd70ed6c36f489a969de697aff93088dbee1a9@35.194.31.108:443"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"go-waku.test": {
|
||||||
|
"libp2p": {
|
||||||
|
"node-01.ac-cn-hongkong-c.go-waku.test": "/ip4/8.218.2.110/tcp/30303/p2p/16Uiu2HAmBDbMWFiG9ki8sDw6fYtraSxo4oHU9HbuN43S2HVyq1FD",
|
||||||
|
"node-01.do-ams3.go-waku.test": "/ip4/134.209.134.63/tcp/30303/p2p/16Uiu2HAm9vnvCQgCDrynDK1h7GJoEZVGvnuzq84RyDQ3DEdXmcX7",
|
||||||
|
"node-01.gc-us-central1-a.go-waku.test": "/ip4/35.223.183.91/tcp/30303/p2p/16Uiu2HAmPz63Xc6AuVkDeujz7YeZta18rcdau3Y1BzaxKAfDrBqz"
|
||||||
|
},
|
||||||
|
"websocket": {
|
||||||
|
"node-01.ac-cn-hongkong-c.go-waku.test": "/dns4/node-01.ac-cn-hongkong-c.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmBDbMWFiG9ki8sDw6fYtraSxo4oHU9HbuN43S2HVyq1FD",
|
||||||
|
"node-01.do-ams3.go-waku.test": "/dns4/node-01.do-ams3.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm9vnvCQgCDrynDK1h7GJoEZVGvnuzq84RyDQ3DEdXmcX7",
|
||||||
|
"node-01.gc-us-central1-a.go-waku.test": "/dns4/node-01.gc-us-central1-a.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPz63Xc6AuVkDeujz7YeZta18rcdau3Y1BzaxKAfDrBqz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wakuv2.prod": {
|
||||||
|
"waku": {
|
||||||
|
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/ip4/8.210.222.231/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
|
||||||
|
"node-01.do-ams3.wakuv2.prod": "/ip4/188.166.135.145/tcp/30303/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
|
||||||
|
"node-01.gc-us-central1-a.wakuv2.prod": "/ip4/34.121.100.108/tcp/30303/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
|
||||||
|
},
|
||||||
|
"waku-websocket": {
|
||||||
|
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD",
|
||||||
|
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
|
||||||
|
"node-01.gc-us-central1-a.wakuv2.prod": "/dns4/node-01.gc-us-central1-a.wakuv2.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmVkKntsECaYfefR1V2yCR79CegLATuTPE6B9TxgxBiiiA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wakuv2.test": {
|
||||||
|
"waku": {
|
||||||
|
"node-01.ac-cn-hongkong-c.wakuv2.test": "/ip4/47.242.210.73/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
|
||||||
|
"node-01.do-ams3.wakuv2.test": "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
|
||||||
|
"node-01.gc-us-central1-a.wakuv2.test": "/ip4/104.154.239.128/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
|
||||||
|
},
|
||||||
|
"waku-websocket": {
|
||||||
|
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm",
|
||||||
|
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
|
||||||
|
"node-01.gc-us-central1-a.wakuv2.test": "/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"hostname": "node-01.do-ams3.sites.misc",
|
||||||
|
"timestamp": "2021-10-19T00:00:15.465044"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
220a1abb4b6943a093c35d0ce4fb0732
|
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
"BrowsersConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
"ClusterConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
"DataDir": "./ethereum/mainnet",
|
||||||
|
"EnableNTPSync": true,
|
||||||
|
"KeyStoreDir": "./keystore",
|
||||||
|
"LogEnabled": true,
|
||||||
|
"LogFile": "./geth.log",
|
||||||
|
"LogLevel": "INFO",
|
||||||
|
"MailserversConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
"Name": "StatusDesktop",
|
||||||
|
"NetworkId": 1,
|
||||||
|
"NoDiscovery": false,
|
||||||
|
"PermissionsConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
"Rendezvous": true,
|
||||||
|
"RegisterTopics": ["whispermail"],
|
||||||
|
"RequireTopics": {
|
||||||
|
"whisper": {
|
||||||
|
"Max": 2,
|
||||||
|
"Min": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ShhextConfig": {
|
||||||
|
"BackupDisabledDataDir": "./",
|
||||||
|
"DataSyncEnabled": true,
|
||||||
|
"InstallationID": "%INSTALLATIONID%",
|
||||||
|
"MailServerConfirmations": true,
|
||||||
|
"MaxMessageDeliveryAttempts": 6,
|
||||||
|
"PFSEnabled": true,
|
||||||
|
"VerifyENSContractAddress": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
|
||||||
|
"VerifyENSURL": "https://mainnet.infura.io/v3/%INFURA_KEY%",
|
||||||
|
"VerifyTransactionChainID": 1,
|
||||||
|
"VerifyTransactionURL": "https://mainnet.infura.io/v3/%INFURA_KEY%"
|
||||||
|
},
|
||||||
|
"StatusAccountsConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
},
|
||||||
|
"UpstreamConfig": {
|
||||||
|
"Enabled": true,
|
||||||
|
"URL": "https://mainnet.infura.io/v3/%INFURA_KEY%"
|
||||||
|
},
|
||||||
|
"WakuConfig": {
|
||||||
|
"BloomFilterMode": null,
|
||||||
|
"Enabled": true,
|
||||||
|
"LightClient": true,
|
||||||
|
"MinimumPoW": 0.001
|
||||||
|
},
|
||||||
|
"WakuV2Config": {
|
||||||
|
"Enabled": false,
|
||||||
|
"Host": "0.0.0.0",
|
||||||
|
"Port": 0,
|
||||||
|
"LightClient": false
|
||||||
|
},
|
||||||
|
"WalletConfig": {
|
||||||
|
"Enabled": true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
add_library(app
|
||||||
|
include/signals.h
|
||||||
|
boot/app_controller.cpp
|
||||||
|
core/signals/signals.cpp
|
||||||
|
global/singleton.cpp
|
||||||
|
modules/startup/controller.cpp
|
||||||
|
modules/startup/module.cpp
|
||||||
|
modules/startup/view.cpp
|
||||||
|
modules/startup/onboarding/controller.cpp
|
||||||
|
modules/startup/onboarding/item.cpp
|
||||||
|
modules/startup/onboarding/model.cpp
|
||||||
|
modules/startup/onboarding/module.cpp
|
||||||
|
modules/startup/onboarding/view.cpp
|
||||||
|
modules/startup/login/controller.cpp
|
||||||
|
modules/startup/login/item.cpp
|
||||||
|
modules/startup/login/model.cpp
|
||||||
|
modules/startup/login/module.cpp
|
||||||
|
modules/startup/login/view.cpp
|
||||||
|
modules/startup/login/selected_account.cpp
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(app
|
||||||
|
PUBLIC
|
||||||
|
./include/
|
||||||
|
./modules/startup
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(app
|
||||||
|
PRIVATE
|
||||||
|
app_service
|
||||||
|
statusgo_shared
|
||||||
|
Qt${QT_VERSION_MAJOR}::Concurrent
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
)
|
|
@ -0,0 +1,237 @@
|
||||||
|
#include "app_controller.h"
|
||||||
|
#include "accounts/service.h"
|
||||||
|
#include "app_service.h"
|
||||||
|
#include "modules/startup/module.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
AppController::AppController()
|
||||||
|
{
|
||||||
|
// result.statusFoundation = statusFoundation
|
||||||
|
|
||||||
|
// # Global
|
||||||
|
// result.localAppSettingsVariant = newQVariant(singletonInstance.localAppSettings)
|
||||||
|
// result.localAccountSettingsVariant = newQVariant(singletonInstance.localAccountSettings)
|
||||||
|
// result.localAccountSensitiveSettingsVariant = newQVariant(singletonInstance.localAccountSensitiveSettings)
|
||||||
|
// result.userProfileVariant = newQVariant(singletonInstance.userProfile)
|
||||||
|
// result.globalUtilsVariant = newQVariant(singletonInstance.utils)
|
||||||
|
|
||||||
|
// # Services
|
||||||
|
// result.settingsService = settings_service.newService()
|
||||||
|
// result.nodeConfigurationService = node_configuration_service.newService(statusFoundation.fleetConfiguration,
|
||||||
|
// result.settingsService)
|
||||||
|
// result.osNotificationService = os_notification_service.newService(statusFoundation.status.events)
|
||||||
|
// result.keychainService = keychain_service.newService(statusFoundation.status.events)
|
||||||
|
// result.ethService = eth_service.newService()
|
||||||
|
m_accountsService = new Accounts::Service();
|
||||||
|
// result.networkService = network_service.newService()
|
||||||
|
// result.contactsService = contacts_service.newService(statusFoundation.status.events, statusFoundation.threadpool)
|
||||||
|
// result.chatService = chat_service.newService(statusFoundation.status.events, result.contactsService)
|
||||||
|
// result.communityService = community_service.newService(statusFoundation.status.events)
|
||||||
|
// result.messageService = message_service.newService(statusFoundation.status.events, statusFoundation.threadpool)
|
||||||
|
// result.activityCenterService = activity_center_service.newService(statusFoundation.status.events,
|
||||||
|
// statusFoundation.threadpool, result.chatService)
|
||||||
|
// result.tokenService = token_service.newService(statusFoundation.status.events, statusFoundation.threadpool,
|
||||||
|
// result.settingsService)
|
||||||
|
// result.collectibleService = collectible_service.newService(result.settingsService)
|
||||||
|
// result.walletAccountService = wallet_account_service.newService(statusFoundation.status.events, result.settingsService,
|
||||||
|
// result.accountsService, result.tokenService)
|
||||||
|
// result.transactionService = transaction_service.newService(statusFoundation.status.events, statusFoundation.threadpool,
|
||||||
|
// result.walletAccountService)
|
||||||
|
// result.bookmarkService = bookmark_service.newService()
|
||||||
|
// result.profileService = profile_service.newService()
|
||||||
|
// result.stickersService = stickers_service.newService(
|
||||||
|
// statusFoundation.status.events,
|
||||||
|
// statusFoundation.threadpool,
|
||||||
|
// result.ethService,
|
||||||
|
// result.settingsService,
|
||||||
|
// result.walletAccountService,
|
||||||
|
// result.transactionService,
|
||||||
|
// result.networkService,
|
||||||
|
// result.chatService
|
||||||
|
// )
|
||||||
|
// result.aboutService = about_service.newService(statusFoundation.status.events, statusFoundation.threadpool,
|
||||||
|
// result.settingsService)
|
||||||
|
// result.dappPermissionsService = dapp_permissions_service.newService()
|
||||||
|
// result.languageService = language_service.newService()
|
||||||
|
// # result.mnemonicService = mnemonic_service.newService()
|
||||||
|
// result.privacyService = privacy_service.newService(statusFoundation.status.events, result.settingsService,
|
||||||
|
// result.accountsService)
|
||||||
|
// result.providerService = provider_service.newService(result.dappPermissionsService, result.settingsService)
|
||||||
|
// result.savedAddressService = saved_address_service.newService(statusFoundation.status.events)
|
||||||
|
// result.devicesService = devices_service.newService(statusFoundation.status.events, result.settingsService)
|
||||||
|
// result.mailserversService = mailservers_service.newService(statusFoundation.status.events, statusFoundation.marathon,
|
||||||
|
// result.settingsService, result.nodeConfigurationService, statusFoundation.fleetConfiguration)
|
||||||
|
|
||||||
|
// # Modules
|
||||||
|
m_startupModule = new Modules::Startup::Module(this, /*keychainService,*/ m_accountsService);
|
||||||
|
|
||||||
|
// result.mainModule = main_module.newModule[AppController](
|
||||||
|
// result,
|
||||||
|
// statusFoundation.status.events,
|
||||||
|
// result.keychainService,
|
||||||
|
// result.accountsService,
|
||||||
|
// result.chatService,
|
||||||
|
// result.communityService,
|
||||||
|
// result.messageService,
|
||||||
|
// result.tokenService,
|
||||||
|
// result.transactionService,
|
||||||
|
// result.collectibleService,
|
||||||
|
// result.walletAccountService,
|
||||||
|
// result.bookmarkService,
|
||||||
|
// result.profileService,
|
||||||
|
// result.settingsService,
|
||||||
|
// result.contactsService,
|
||||||
|
// result.aboutService,
|
||||||
|
// result.dappPermissionsService,
|
||||||
|
// result.languageService,
|
||||||
|
// # result.mnemonicService,
|
||||||
|
// result.privacyService,
|
||||||
|
// result.providerService,
|
||||||
|
// result.stickersService,
|
||||||
|
// result.activityCenterService,
|
||||||
|
// result.savedAddressService,
|
||||||
|
// result.nodeConfigurationService,
|
||||||
|
// result.devicesService,
|
||||||
|
// result.mailserversService
|
||||||
|
// )
|
||||||
|
|
||||||
|
// # Do connections
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppController::~AppController()
|
||||||
|
{
|
||||||
|
delete m_startupModule;
|
||||||
|
|
||||||
|
delete m_accountsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::connect()
|
||||||
|
{
|
||||||
|
// self.statusFoundation.status.events.once("nodeStopped") do(a: Args):
|
||||||
|
// TODO: remove this once accounts are not tracked in the AccountsModel
|
||||||
|
// self.statusFoundation.status.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::startupDidLoad()
|
||||||
|
{
|
||||||
|
// singletonInstance.engine.setRootContextProperty("localAppSettings", self.localAppSettingsVariant)
|
||||||
|
// singletonInstance.engine.setRootContextProperty("localAccountSettings", self.localAccountSettingsVariant)
|
||||||
|
// singletonInstance.engine.load(newQUrl("qrc:///main.qml"))
|
||||||
|
|
||||||
|
// We need to init a language service once qml is loaded
|
||||||
|
// self.languageService.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::mainDidLoad()
|
||||||
|
{
|
||||||
|
//self.statusFoundation.onLoggedIn()
|
||||||
|
m_startupModule->moveToAppState();
|
||||||
|
|
||||||
|
//self.mainModule.checkForStoringPassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::start()
|
||||||
|
{
|
||||||
|
// self.ethService.init()
|
||||||
|
m_accountsService->init();
|
||||||
|
|
||||||
|
m_startupModule->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::load()
|
||||||
|
{
|
||||||
|
qWarning() << "TODO: init services and load main module";
|
||||||
|
// self.settingsService.init()
|
||||||
|
// self.nodeConfigurationService.init()
|
||||||
|
// self.contactsService.init()
|
||||||
|
// self.chatService.init()
|
||||||
|
// self.messageService.init()
|
||||||
|
// self.communityService.init()
|
||||||
|
// self.bookmarkService.init()
|
||||||
|
// self.tokenService.init()
|
||||||
|
// self.dappPermissionsService.init()
|
||||||
|
// self.providerService.init()
|
||||||
|
// self.walletAccountService.init()
|
||||||
|
// self.transactionService.init()
|
||||||
|
// self.stickersService.init()
|
||||||
|
// self.networkService.init()
|
||||||
|
// self.activityCenterService.init()
|
||||||
|
// self.savedAddressService.init()
|
||||||
|
// self.aboutService.init()
|
||||||
|
// self.devicesService.init()
|
||||||
|
// self.mailserversService.init()
|
||||||
|
|
||||||
|
// let pubKey = self.settingsService.getPublicKey()
|
||||||
|
// singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)
|
||||||
|
// singletonInstance.engine.setRootContextProperty("localAccountSensitiveSettings", self.localAccountSensitiveSettingsVariant)
|
||||||
|
// singletonInstance.engine.setRootContextProperty("globalUtils", self.globalUtilsVariant)
|
||||||
|
|
||||||
|
// # other global instances
|
||||||
|
// self.buildAndRegisterLocalAccountSensitiveSettings()
|
||||||
|
// self.buildAndRegisterUserProfile()
|
||||||
|
|
||||||
|
// # load main module
|
||||||
|
// self.mainModule.load(
|
||||||
|
// self.statusFoundation.status.events,
|
||||||
|
// self.settingsService,
|
||||||
|
// self.contactsService,
|
||||||
|
// self.chatService,
|
||||||
|
// self.communityService,
|
||||||
|
// self.messageService
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::userLoggedIn()
|
||||||
|
{
|
||||||
|
//self.statusFoundation.status.startMessenger()
|
||||||
|
AppController::load();
|
||||||
|
|
||||||
|
// Once user is logged in and main module is loaded we need to check if it gets here importing mnemonic or not
|
||||||
|
// and delete mnemonic in the first case.
|
||||||
|
auto importedAccount = m_accountsService->getImportedAccount();
|
||||||
|
if(importedAccount.isValid())
|
||||||
|
{
|
||||||
|
// self.privacyService.removeMnemonic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::buildAndRegisterLocalAccountSensitiveSettings()
|
||||||
|
{
|
||||||
|
|
||||||
|
// var pubKey = self.settingsService.getPublicKey()
|
||||||
|
// singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)
|
||||||
|
// singletonInstance.engine.setRootContextProperty("localAccountSensitiveSettings", self.localAccountSensitiveSettingsVariant)
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppController::buildAndRegisterUserProfile()
|
||||||
|
{
|
||||||
|
// let pubKey = self.settingsService.getPublicKey()
|
||||||
|
// let preferredName = self.settingsService.getPreferredName()
|
||||||
|
// let ensUsernames = self.settingsService.getEnsUsernames()
|
||||||
|
// let firstEnsName = if (ensUsernames.len > 0): ensUsernames[0] else: ""
|
||||||
|
// let sendUserStatus = self.settingsService.getSendStatusUpdates()
|
||||||
|
// // This is still not in use. Read a comment in UserProfile.
|
||||||
|
// // let currentUserStatus = self.settingsService.getCurrentUserStatus()
|
||||||
|
|
||||||
|
// let loggedInAccount = self.accountsService.getLoggedInAccount()
|
||||||
|
// var thumbnail, large: string
|
||||||
|
// for img in loggedInAccount.images:
|
||||||
|
// if(img.imgType == "large"):
|
||||||
|
// large = img.uri
|
||||||
|
// elif(img.imgType == "thumbnail"):
|
||||||
|
// thumbnail = img.uri
|
||||||
|
|
||||||
|
// let meAsContact = self.contactsService.getContactById(pubKey)
|
||||||
|
|
||||||
|
// singletonInstance.userProfile.setFixedData(loggedInAccount.name, loggedInAccount.keyUid, loggedInAccount.identicon,
|
||||||
|
// pubKey)
|
||||||
|
// singletonInstance.userProfile.setPreferredName(preferredName)
|
||||||
|
// singletonInstance.userProfile.setEnsName(meAsContact.name)
|
||||||
|
// singletonInstance.userProfile.setFirstEnsName(firstEnsName)
|
||||||
|
// singletonInstance.userProfile.setThumbnailImage(thumbnail)
|
||||||
|
// singletonInstance.userProfile.setLargeImage(large)
|
||||||
|
// singletonInstance.userProfile.setUserStatus(sendUserStatus)
|
||||||
|
|
||||||
|
// singletonInstance.engine.setRootContextProperty("userProfile", self.userProfileVariant)
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include "signals.h"
|
||||||
|
#include "libstatus.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
namespace Signals
|
||||||
|
{
|
||||||
|
|
||||||
|
Manager* Manager::theInstance;
|
||||||
|
|
||||||
|
Manager* Manager::instance()
|
||||||
|
{
|
||||||
|
if(theInstance == 0) theInstance = new Manager();
|
||||||
|
return theInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<QString, SignalType> Manager::signalMap;
|
||||||
|
|
||||||
|
Manager::Manager(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
SetSignalEventCallback((void*)&Manager::signalCallback);
|
||||||
|
|
||||||
|
signalMap = {{"node.ready", SignalType::NodeReady},
|
||||||
|
{"node.started", SignalType::NodeStarted},
|
||||||
|
{"node.stopped", SignalType::NodeStopped},
|
||||||
|
{"node.login", SignalType::NodeLogin},
|
||||||
|
{"node.crashed", SignalType::NodeCrashed}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::processSignal(QString statusSignal)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QJsonParseError json_error;
|
||||||
|
const QJsonDocument signalEventDoc(QJsonDocument::fromJson(statusSignal.toUtf8(), &json_error));
|
||||||
|
if(json_error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
qWarning() << "Invalid signal received";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
decode(signalEventDoc.object());
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
qWarning() << "Error decoding signal, err: ", e.what();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::decode(const QJsonObject& signalEvent)
|
||||||
|
{
|
||||||
|
SignalType signalType(Unknown);
|
||||||
|
if(!signalMap.count(signalEvent["type"].toString()))
|
||||||
|
{
|
||||||
|
qWarning() << "Unknown signal received: " << signalEvent["type"].toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
signalType = signalMap[signalEvent["type"].toString()];
|
||||||
|
|
||||||
|
switch(signalType)
|
||||||
|
{
|
||||||
|
// TODO: create extractor functions like in nim
|
||||||
|
case NodeLogin: emit instance()->nodeLogin(NodeSignal{signalType, signalEvent["event"]["error"].toString()}); break;
|
||||||
|
case NodeReady: emit instance()->nodeReady(NodeSignal{signalType, signalEvent["event"]["error"].toString()}); break;
|
||||||
|
case NodeStarted:
|
||||||
|
emit instance()->nodeStarted(NodeSignal{signalType, signalEvent["event"]["error"].toString()});
|
||||||
|
break;
|
||||||
|
case NodeStopped:
|
||||||
|
emit instance()->nodeStopped(NodeSignal{signalType, signalEvent["event"]["error"].toString()});
|
||||||
|
break;
|
||||||
|
case NodeCrashed: {
|
||||||
|
auto signal = NodeSignal{signalType, signalEvent["event"]["error"].toString()};
|
||||||
|
qWarning() << "node.crashed, error: " << signal.error;
|
||||||
|
emit instance()->nodeCrashed(signal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: qWarning() << "Signal decoding not implemented: " << signalEvent; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::signalCallback(const char* data)
|
||||||
|
{
|
||||||
|
QtConcurrent::run(instance(), &Manager::processSignal, QString(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Signals
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "singleton.h"
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
namespace Global
|
||||||
|
{
|
||||||
|
Singleton* Singleton::theInstance;
|
||||||
|
|
||||||
|
Singleton* Singleton::instance()
|
||||||
|
{
|
||||||
|
if(theInstance == 0) theInstance = new Singleton();
|
||||||
|
return theInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Singleton::Singleton()
|
||||||
|
{
|
||||||
|
m_engine = new QQmlApplicationEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlApplicationEngine* Singleton::engine()
|
||||||
|
{
|
||||||
|
return m_engine;
|
||||||
|
}
|
||||||
|
} // namespace Global
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service.h"
|
||||||
|
#include "module_access_interface.h"
|
||||||
|
#include "app_controller_delegate.h"
|
||||||
|
#include "app_service.h"
|
||||||
|
|
||||||
|
class AppController : public AppControllerDelegate
|
||||||
|
{
|
||||||
|
//statusFoundation: StatusFoundation
|
||||||
|
|
||||||
|
// Global
|
||||||
|
//localAppSettingsVariant: QVariant
|
||||||
|
//localAccountSettingsVariant: QVariant
|
||||||
|
//localAccountSensitiveSettingsVariant: QVariant
|
||||||
|
//userProfileVariant: QVariant
|
||||||
|
//globalUtilsVariant: QVariant
|
||||||
|
|
||||||
|
// Services
|
||||||
|
Accounts::Service* m_accountsService;
|
||||||
|
|
||||||
|
// Modules
|
||||||
|
Modules::Startup::ModuleAccessInterface* m_startupModule;
|
||||||
|
//mainModule: main_module.AccessInterface
|
||||||
|
|
||||||
|
public:
|
||||||
|
AppController();
|
||||||
|
~AppController();
|
||||||
|
void start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void connect();
|
||||||
|
void startupDidLoad() override;
|
||||||
|
void mainDidLoad();
|
||||||
|
void load();
|
||||||
|
void userLoggedIn() override;
|
||||||
|
void buildAndRegisterLocalAccountSensitiveSettings();
|
||||||
|
void buildAndRegisterUserProfile();
|
||||||
|
};
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class AppControllerDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void startupDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void userLoggedIn()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QVariantList>
|
||||||
|
|
||||||
|
namespace Signals
|
||||||
|
{
|
||||||
|
Q_NAMESPACE
|
||||||
|
|
||||||
|
enum SignalType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
NodeLogin,
|
||||||
|
NodeReady,
|
||||||
|
NodeStarted,
|
||||||
|
NodeStopped,
|
||||||
|
NodeCrashed
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_ENUM_NS(SignalType)
|
||||||
|
|
||||||
|
struct Signal
|
||||||
|
{
|
||||||
|
SignalType signalType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NodeSignal : Signal
|
||||||
|
{
|
||||||
|
QString error;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Manager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Manager* instance();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void signal(SignalType signal);
|
||||||
|
|
||||||
|
void nodeReady(NodeSignal signal);
|
||||||
|
void nodeStarted(NodeSignal signal);
|
||||||
|
void nodeStopped(NodeSignal signal);
|
||||||
|
void nodeLogin(NodeSignal signal);
|
||||||
|
void nodeCrashed(NodeSignal signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Manager* theInstance;
|
||||||
|
explicit Manager(QObject* parent = nullptr);
|
||||||
|
static std::map<QString, SignalType> signalMap;
|
||||||
|
static void signalCallback(const char* data);
|
||||||
|
void processSignal(QString ev);
|
||||||
|
void decode(const QJsonObject& signalEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Signals
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Signals::Signal)
|
||||||
|
Q_DECLARE_METATYPE(Signals::NodeSignal)
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
|
||||||
|
namespace Global
|
||||||
|
{
|
||||||
|
|
||||||
|
class Singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QQmlApplicationEngine* engine();
|
||||||
|
static Singleton* instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Singleton* theInstance;
|
||||||
|
explicit Singleton();
|
||||||
|
QQmlApplicationEngine* m_engine;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Global
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "controller.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
Controller::Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_accountsService(accountsService)
|
||||||
|
, m_delegate(d)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void Controller::init()
|
||||||
|
{
|
||||||
|
QObject::connect(Signals::Manager::instance(), &Signals::Manager::nodeLogin, this, &Controller::onLogin);
|
||||||
|
QObject::connect(Signals::Manager::instance(), &Signals::Manager::nodeStopped, this, &Controller::onNodeStopped);
|
||||||
|
QObject::connect(Signals::Manager::instance(), &Signals::Manager::nodeReady, this, &Controller::onNodeReady);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::onLogin(Signals::NodeSignal signal)
|
||||||
|
{
|
||||||
|
if(signal.error.isEmpty())
|
||||||
|
{
|
||||||
|
m_delegate->userLoggedIn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << "error: methodName=init, errDescription=login error " << signal.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::onNodeStopped(Signals::NodeSignal signal)
|
||||||
|
{
|
||||||
|
// self.events.emit("nodeStopped", Args())
|
||||||
|
m_accountsService->clear();
|
||||||
|
m_delegate->emitLogOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::onNodeReady(Signals::NodeSignal signal)
|
||||||
|
{
|
||||||
|
// self.events.emit("nodeReady", Args())
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Controller::shouldStartWithOnboardingScreen()
|
||||||
|
{
|
||||||
|
return m_accountsService->openedAccounts().size() == 0;
|
||||||
|
}
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
|
||||||
|
class Controller : public QObject, ControllerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent = nullptr);
|
||||||
|
void init() override;
|
||||||
|
bool shouldStartWithOnboardingScreen() override;
|
||||||
|
void onLogin(Signals::NodeSignal signal);
|
||||||
|
void onNodeStopped(Signals::NodeSignal signal);
|
||||||
|
void onNodeReady(Signals::NodeSignal signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Accounts::ServiceInterface* m_accountsService;
|
||||||
|
ModuleControllerDelegateInterface* m_delegate;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
|
||||||
|
// Abstract class for any input/interaction with this module.
|
||||||
|
|
||||||
|
class ControllerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void init()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual bool shouldStartWithOnboardingScreen()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "app_controller_delegate.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class ModuleControllerDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void userLoggedIn()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void emitLogOut()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class ModuleLoginDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void loginDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class ModuleOnboardingDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void onboardingDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void viewDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,87 @@
|
||||||
|
#include "controller.h"
|
||||||
|
#include "accounts/account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
Controller::Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
// keychainService
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_accountsService(accountsService)
|
||||||
|
, m_delegate(d)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void Controller::init()
|
||||||
|
{
|
||||||
|
QObject::connect(Signals::Manager::instance(), &Signals::Manager::nodeLogin, this, &Controller::onLogin);
|
||||||
|
// keychainServiceSuccess see src-cpp/app/modules/startup/login/controller.nim line 43
|
||||||
|
// keychainServiceError see src-cpp/app/modules/startup/login/controller.nim line 47
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::onLogin(Signals::NodeSignal signal)
|
||||||
|
{
|
||||||
|
if(!signal.error.isEmpty())
|
||||||
|
{
|
||||||
|
m_delegate->emitAccountLoginError(signal.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<Accounts::AccountDto> Controller::getOpenedAccounts()
|
||||||
|
{
|
||||||
|
return m_accountsService->openedAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::AccountDto Controller::getSelectedAccount()
|
||||||
|
{
|
||||||
|
auto openedAccounts = Controller::getOpenedAccounts();
|
||||||
|
foreach(const Accounts::AccountDto& acc, openedAccounts)
|
||||||
|
{
|
||||||
|
if(acc.keyUid == m_selectedAccountKeyUid)
|
||||||
|
{
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::setSelectedAccountKeyUid(QString keyUid)
|
||||||
|
{
|
||||||
|
m_selectedAccountKeyUid = keyUid;
|
||||||
|
|
||||||
|
// Dealing with Keychain is the MacOS only feature
|
||||||
|
// if(not defined(macosx)):
|
||||||
|
// return
|
||||||
|
|
||||||
|
// let selectedAccount = self.getSelectedAccount()
|
||||||
|
// singletonInstance.localAccountSettings.setFileName(selectedAccount.name)
|
||||||
|
|
||||||
|
// let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||||
|
// if (value != LS_VALUE_STORE):
|
||||||
|
// return
|
||||||
|
|
||||||
|
// self.keychainService.tryToObtainPassword(selectedAccount.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::login(QString password)
|
||||||
|
{
|
||||||
|
auto selectedAccount = Controller::getSelectedAccount();
|
||||||
|
auto error = m_accountsService->login(selectedAccount, password);
|
||||||
|
if(!error.isEmpty())
|
||||||
|
{
|
||||||
|
m_delegate->emitAccountLoginError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class Controller : public QObject, ControllerInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
// keychainService,
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent = nullptr);
|
||||||
|
void init() override;
|
||||||
|
QVector<Accounts::AccountDto> getOpenedAccounts() override;
|
||||||
|
Accounts::AccountDto getSelectedAccount();
|
||||||
|
void setSelectedAccountKeyUid(QString keyUid) override;
|
||||||
|
void login(QString password) override;
|
||||||
|
void onLogin(Signals::NodeSignal signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Keychain::m_keychainService
|
||||||
|
Accounts::ServiceInterface* m_accountsService;
|
||||||
|
ModuleControllerDelegateInterface* m_delegate;
|
||||||
|
QString m_selectedAccountKeyUid;
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/account.h"
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
|
||||||
|
// Abstract class for any input/interaction with this module.
|
||||||
|
|
||||||
|
class ControllerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void init()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual QVector<Accounts::AccountDto> getOpenedAccounts()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual void setSelectedAccountKeyUid(QString keyUid)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual void login(QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "app_controller_delegate.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class ModuleControllerDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void emitAccountLoginError(QString error)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void emitObtainingPasswordError(QString errorDescription)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void emitObtainingPasswordSuccess(QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Login
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../item.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void viewDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setSelectedAccount(Item item)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void login(QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Login
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include "item.h"
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
Item::Item() { }
|
||||||
|
|
||||||
|
Item::Item(QString name, QString identicon, QString thumbnailImage, QString largeImage, QString keyUid)
|
||||||
|
: m_name(name)
|
||||||
|
, m_identicon(identicon)
|
||||||
|
, m_thumbnailImage(thumbnailImage)
|
||||||
|
, m_largeImage(largeImage)
|
||||||
|
, m_keyUid(keyUid)
|
||||||
|
{ }
|
||||||
|
QString Item::getName()
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
QString Item::getIdenticon()
|
||||||
|
{
|
||||||
|
return m_identicon;
|
||||||
|
}
|
||||||
|
QString Item::getThumbnailImage()
|
||||||
|
{
|
||||||
|
return m_thumbnailImage;
|
||||||
|
}
|
||||||
|
QString Item::getLargeImage()
|
||||||
|
{
|
||||||
|
return m_largeImage;
|
||||||
|
}
|
||||||
|
QString Item::getKeyUid()
|
||||||
|
{
|
||||||
|
return m_keyUid;
|
||||||
|
}
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class Item
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QString m_name;
|
||||||
|
QString m_identicon;
|
||||||
|
QString m_thumbnailImage;
|
||||||
|
QString m_largeImage;
|
||||||
|
QString m_keyUid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Item();
|
||||||
|
Item(QString name, QString identicon, QString thumbnailImage, QString largeImage, QString keyUid);
|
||||||
|
QString getName();
|
||||||
|
QString getIdenticon();
|
||||||
|
QString getThumbnailImage();
|
||||||
|
QString getLargeImage();
|
||||||
|
QString getKeyUid();
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include "model.h"
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
Model::Model(QObject* parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
QHash<int, QByteArray> Model::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles[Name] = "username";
|
||||||
|
roles[Identicon] = "identicon";
|
||||||
|
roles[ThumbnailImage] = "thumbnailImage";
|
||||||
|
roles[LargeImage] = "largeImage";
|
||||||
|
roles[KeyUid] = "keyUid";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model::rowCount(const QModelIndex& parent = QModelIndex()) const
|
||||||
|
{
|
||||||
|
return m_items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant Model::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
if(!index.isValid())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index.row() < 0 || index.row() > m_items.size())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item = m_items[index.row()];
|
||||||
|
|
||||||
|
switch(role)
|
||||||
|
{
|
||||||
|
case Name: return QVariant(item.getName());
|
||||||
|
case Identicon: return QVariant(item.getIdenticon());
|
||||||
|
case ThumbnailImage: return QVariant(item.getThumbnailImage());
|
||||||
|
case LargeImage: return QVariant(item.getLargeImage());
|
||||||
|
case KeyUid: return QVariant(item.getKeyUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::setItems(QVector<Item> items)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_items = items;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
Item Model::getItemAtIndex(int index)
|
||||||
|
{
|
||||||
|
if(index < 0 || index >= m_items.size())
|
||||||
|
{
|
||||||
|
return Item();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_items[index];
|
||||||
|
}
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "item.h"
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class Model : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ModelRole
|
||||||
|
{
|
||||||
|
Name = Qt::UserRole + 1,
|
||||||
|
Identicon = Qt::UserRole + 2,
|
||||||
|
ThumbnailImage = Qt::UserRole + 3,
|
||||||
|
LargeImage = Qt::UserRole + 4,
|
||||||
|
KeyUid = Qt::UserRole + 5
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Model(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const;
|
||||||
|
virtual int rowCount(const QModelIndex&) const;
|
||||||
|
virtual QVariant data(const QModelIndex& index, int role) const;
|
||||||
|
void setItems(QVector<Item> items);
|
||||||
|
Item getItemAtIndex(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<Item> m_items;
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include "module.h"
|
||||||
|
#include "../interfaces/module_login_delegate_interface.h"
|
||||||
|
#include "accounts/account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
Module::Module(Modules::Startup::ModuleLoginDelegateInterface* d,
|
||||||
|
// keychainService
|
||||||
|
Accounts::ServiceInterface* accountsService)
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
m_controller = new Controller(this, accountsService);
|
||||||
|
m_view = new View(this);
|
||||||
|
m_moduleLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::~Module()
|
||||||
|
{
|
||||||
|
delete m_controller;
|
||||||
|
delete m_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::extractImages(Accounts::AccountDto account, QString &thumbnailImage, QString &largeImage)
|
||||||
|
{
|
||||||
|
foreach(const Accounts::Image& img, account.images)
|
||||||
|
{
|
||||||
|
if(img.imgType == "thumbnail")
|
||||||
|
{
|
||||||
|
thumbnailImage = img.uri;
|
||||||
|
}
|
||||||
|
else if(img.imgType == "large")
|
||||||
|
{
|
||||||
|
largeImage = img.uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::load()
|
||||||
|
{
|
||||||
|
Global::Singleton::instance()->engine()->rootContext()->setContextProperty("loginModule", m_view);
|
||||||
|
m_controller->init();
|
||||||
|
m_view->load();
|
||||||
|
|
||||||
|
QVector<Accounts::AccountDto> openedAccounts = m_controller->getOpenedAccounts();
|
||||||
|
if(openedAccounts.size() > 0)
|
||||||
|
{
|
||||||
|
QVector<Item> items;
|
||||||
|
foreach(const Accounts::AccountDto& acc, openedAccounts)
|
||||||
|
{
|
||||||
|
QString thumbnailImage;
|
||||||
|
QString largeImage;
|
||||||
|
Module::extractImages(acc, thumbnailImage, largeImage);
|
||||||
|
items << Item(acc.name, acc.identicon, thumbnailImage, largeImage, acc.keyUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_view->setModelItems(items);
|
||||||
|
|
||||||
|
// set the first account as slected one
|
||||||
|
m_controller->setSelectedAccountKeyUid(items[0].getKeyUid());
|
||||||
|
Module::setSelectedAccount(items[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Module::isLoaded()
|
||||||
|
{
|
||||||
|
return m_moduleLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::viewDidLoad()
|
||||||
|
{
|
||||||
|
m_moduleLoaded = true;
|
||||||
|
m_delegate->loginDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::setSelectedAccount(Item item)
|
||||||
|
{
|
||||||
|
m_controller->setSelectedAccountKeyUid(item.getKeyUid());
|
||||||
|
m_view->setSelectedAccount(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::login(QString password)
|
||||||
|
{
|
||||||
|
m_controller->login(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::emitAccountLoginError(QString error)
|
||||||
|
{
|
||||||
|
m_view->emitAccountLoginError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::emitObtainingPasswordError(QString errorDescription)
|
||||||
|
{
|
||||||
|
m_view->emitObtainingPasswordError(errorDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::emitObtainingPasswordSuccess(QString password)
|
||||||
|
{
|
||||||
|
m_view->emitObtainingPasswordSuccess(password);
|
||||||
|
}
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../interfaces/module_login_delegate_interface.h"
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "item.h"
|
||||||
|
#include "module_access_interface.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class Module : public ModuleAccessInterface, ModuleControllerDelegateInterface, ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Modules::Startup::ModuleLoginDelegateInterface* m_delegate;
|
||||||
|
View* m_view;
|
||||||
|
Controller* m_controller;
|
||||||
|
bool m_moduleLoaded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Module(Modules::Startup::ModuleLoginDelegateInterface* d,
|
||||||
|
// keychainService
|
||||||
|
Accounts::ServiceInterface* accountsService);
|
||||||
|
~Module();
|
||||||
|
void extractImages(Accounts::AccountDto account, QString &thumbnailImage, QString &largeImage);
|
||||||
|
void load() override;
|
||||||
|
bool isLoaded() override;
|
||||||
|
void viewDidLoad() override;
|
||||||
|
void setSelectedAccount(Item item) override;
|
||||||
|
void login(QString password) override;
|
||||||
|
void setupAccountError();
|
||||||
|
void emitAccountLoginError(QString error) override;
|
||||||
|
void emitObtainingPasswordError(QString errorDescription) override;
|
||||||
|
void emitObtainingPasswordSuccess(QString password) override;
|
||||||
|
};
|
||||||
|
}; // namespace Login
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
class ModuleAccessInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void load()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isLoaded()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Login
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "selected_account.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
SelectedAccount::SelectedAccount(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void SelectedAccount::setSelectedAccountData(Item item)
|
||||||
|
{
|
||||||
|
m_item = item;
|
||||||
|
}
|
||||||
|
QString SelectedAccount::getName()
|
||||||
|
{
|
||||||
|
return m_item.getName();
|
||||||
|
}
|
||||||
|
QString SelectedAccount::getIdenticon()
|
||||||
|
{
|
||||||
|
return m_item.getIdenticon();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SelectedAccount::getKeyUid()
|
||||||
|
{
|
||||||
|
return m_item.getKeyUid();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SelectedAccount::getThumbnailImage()
|
||||||
|
{
|
||||||
|
return m_item.getThumbnailImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SelectedAccount::getLargeImage()
|
||||||
|
{
|
||||||
|
return m_item.getLargeImage();
|
||||||
|
}
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include "item.h"
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
|
||||||
|
class SelectedAccount : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString username READ getName CONSTANT)
|
||||||
|
Q_PROPERTY(QString identicon READ getIdenticon CONSTANT)
|
||||||
|
Q_PROPERTY(QString keyUid READ getKeyUid CONSTANT)
|
||||||
|
Q_PROPERTY(QString thumbnailImage READ getThumbnailImage CONSTANT)
|
||||||
|
Q_PROPERTY(QString largeImage READ getLargeImage CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SelectedAccount(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Item m_item;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setSelectedAccountData(Item item);
|
||||||
|
QString getName();
|
||||||
|
QString getIdenticon();
|
||||||
|
QString getKeyUid();
|
||||||
|
QString getThumbnailImage();
|
||||||
|
QString getLargeImage();
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include "view.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "selected_account.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
View::View(ModuleViewDelegateInterface* d, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
m_model = new Model();
|
||||||
|
m_selectedAccount = new SelectedAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
View::~View()
|
||||||
|
{
|
||||||
|
delete m_model;
|
||||||
|
delete m_selectedAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::load()
|
||||||
|
{
|
||||||
|
m_delegate->viewDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
Model* View::getModel()
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedAccount* View::getSelectedAccount()
|
||||||
|
{
|
||||||
|
return m_selectedAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setSelectedAccount(Item item)
|
||||||
|
{
|
||||||
|
m_selectedAccount->setSelectedAccountData(item);
|
||||||
|
View::selectedAccountChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
Item item = m_model->getItemAtIndex(index);
|
||||||
|
m_delegate->setSelectedAccount(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setModelItems(QVector<Item> accounts)
|
||||||
|
{
|
||||||
|
m_model->setItems(accounts);
|
||||||
|
View::modelChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::login(QString password)
|
||||||
|
{
|
||||||
|
m_delegate->login(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::emitAccountLoginError(QString error)
|
||||||
|
{
|
||||||
|
emit View::accountLoginError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::emitObtainingPasswordError(QString errorDescription)
|
||||||
|
{
|
||||||
|
emit View::obtainingPasswordError(errorDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::emitObtainingPasswordSuccess(QString password)
|
||||||
|
{
|
||||||
|
emit View::obtainingPasswordSuccess(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "selected_account.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Login
|
||||||
|
{
|
||||||
|
|
||||||
|
class View : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(SelectedAccount* selectedAccount READ getSelectedAccount NOTIFY selectedAccountChanged)
|
||||||
|
Q_PROPERTY(Model* accountsModel READ getModel NOTIFY modelChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit View(ModuleViewDelegateInterface* d, QObject* parent = nullptr);
|
||||||
|
~View();
|
||||||
|
void load();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void selectedAccountChanged();
|
||||||
|
void modelChanged();
|
||||||
|
void accountLoginError(QString error);
|
||||||
|
void obtainingPasswordError(QString errorDescription);
|
||||||
|
void obtainingPasswordSuccess(QString password);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModuleViewDelegateInterface* m_delegate;
|
||||||
|
Model* m_model;
|
||||||
|
SelectedAccount* m_selectedAccount;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
Model* getModel();
|
||||||
|
SelectedAccount* getSelectedAccount();
|
||||||
|
void setSelectedAccount(Item item);
|
||||||
|
void setSelectedAccountByIndex(int index);
|
||||||
|
void setModelItems(QVector<Item> accounts);
|
||||||
|
void login(QString password);
|
||||||
|
void emitAccountLoginError(QString error);
|
||||||
|
void emitObtainingPasswordError(QString errorDescription);
|
||||||
|
void emitObtainingPasswordSuccess(QString password);
|
||||||
|
};
|
||||||
|
} // namespace Login
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include "module.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "modules/startup/login/module.h"
|
||||||
|
#include "modules/startup/onboarding/module.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
Module::Module(AppControllerDelegate* d,
|
||||||
|
/*keychainService,*/
|
||||||
|
Accounts::ServiceInterface* accountsService)
|
||||||
|
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
m_controller = new Controller(this, accountsService);
|
||||||
|
m_view = new View(this);
|
||||||
|
|
||||||
|
// Submodules
|
||||||
|
m_onboardingModule = new Modules::Startup::Onboarding::Module(this, accountsService);
|
||||||
|
m_loginModule = new Modules::Startup::Login::Module(this, /*keychainService, */ accountsService);
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::~Module()
|
||||||
|
{
|
||||||
|
delete m_controller;
|
||||||
|
delete m_view;
|
||||||
|
delete m_onboardingModule;
|
||||||
|
delete m_loginModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::load()
|
||||||
|
{
|
||||||
|
Global::Singleton::instance()->engine()->rootContext()->setContextProperty("startupModule", m_view);
|
||||||
|
m_controller->init();
|
||||||
|
m_view->load();
|
||||||
|
|
||||||
|
AppState initialAppState(AppState::OnboardingState);
|
||||||
|
if(!m_controller->shouldStartWithOnboardingScreen())
|
||||||
|
{
|
||||||
|
initialAppState = AppState::LoginState;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_view->setAppState(initialAppState);
|
||||||
|
|
||||||
|
m_onboardingModule->load();
|
||||||
|
m_loginModule->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::checkIfModuleDidLoad()
|
||||||
|
{
|
||||||
|
if(!m_onboardingModule->isLoaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_loginModule->isLoaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_delegate->startupDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::viewDidLoad()
|
||||||
|
{
|
||||||
|
Module::checkIfModuleDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::onboardingDidLoad()
|
||||||
|
{
|
||||||
|
Module::checkIfModuleDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::loginDidLoad()
|
||||||
|
{
|
||||||
|
Module::checkIfModuleDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::userLoggedIn()
|
||||||
|
{
|
||||||
|
m_delegate->userLoggedIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::moveToAppState()
|
||||||
|
{
|
||||||
|
m_view->setAppState(AppState::MainAppState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::emitLogOut()
|
||||||
|
{
|
||||||
|
m_view->emitLogOut();
|
||||||
|
}
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "app_controller_delegate.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "interfaces/module_login_delegate_interface.h"
|
||||||
|
#include "interfaces/module_onboarding_delegate_interface.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "login/module_access_interface.h"
|
||||||
|
#include "module_access_interface.h"
|
||||||
|
#include "onboarding/module_access_interface.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class Module : public ModuleAccessInterface,
|
||||||
|
ModuleOnboardingDelegateInterface,
|
||||||
|
ModuleLoginDelegateInterface,
|
||||||
|
ModuleControllerDelegateInterface,
|
||||||
|
ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
AppControllerDelegate* m_delegate;
|
||||||
|
View* m_view;
|
||||||
|
Controller* m_controller;
|
||||||
|
|
||||||
|
Modules::Startup::Onboarding::ModuleAccessInterface* m_onboardingModule;
|
||||||
|
Modules::Startup::Login::ModuleAccessInterface* m_loginModule;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Module(AppControllerDelegate* d,
|
||||||
|
/*keychainService,*/ Accounts::ServiceInterface* accountsService);
|
||||||
|
~Module();
|
||||||
|
void load() override;
|
||||||
|
void checkIfModuleDidLoad();
|
||||||
|
void viewDidLoad() override;
|
||||||
|
void onboardingDidLoad();
|
||||||
|
void loginDidLoad();
|
||||||
|
void userLoggedIn() override;
|
||||||
|
void moveToAppState() override;
|
||||||
|
void emitLogOut() override;
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
class ModuleAccessInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void load()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void moveToAppState()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "controller.h"
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
Controller::Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_accountsService(accountsService)
|
||||||
|
, m_delegate(d)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void Controller::init()
|
||||||
|
{
|
||||||
|
QObject::connect(Signals::Manager::instance(), &Signals::Manager::nodeLogin, this, &Controller::onLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::onLogin(Signals::NodeSignal signal)
|
||||||
|
{
|
||||||
|
if(!signal.error.isEmpty())
|
||||||
|
{
|
||||||
|
m_delegate->setupAccountError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<Accounts::GeneratedAccountDto> Controller::getGeneratedAccounts()
|
||||||
|
{
|
||||||
|
return m_accountsService->generatedAccounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::GeneratedAccountDto Controller::getImportedAccount()
|
||||||
|
{
|
||||||
|
return m_accountsService->getImportedAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
auto accounts = Controller::getGeneratedAccounts();
|
||||||
|
m_selectedAccountId = accounts[index].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::storeSelectedAccountAndLogin(QString password)
|
||||||
|
{
|
||||||
|
if(!m_accountsService->setupAccount(m_selectedAccountId, password))
|
||||||
|
{
|
||||||
|
m_delegate->setupAccountError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Controller::validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
return m_accountsService->validateMnemonic(mnemonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
if(m_accountsService->importMnemonic(mnemonic))
|
||||||
|
{
|
||||||
|
m_selectedAccountId = Controller::getImportedAccount().id;
|
||||||
|
m_delegate->importAccountSuccess();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_delegate->importAccountError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller_interface.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "signals.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class Controller : public QObject, ControllerInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Controller(ModuleControllerDelegateInterface* d,
|
||||||
|
Accounts::ServiceInterface* accountsService,
|
||||||
|
QObject* parent = nullptr);
|
||||||
|
void init() override;
|
||||||
|
QVector<Accounts::GeneratedAccountDto> getGeneratedAccounts() override;
|
||||||
|
Accounts::GeneratedAccountDto getImportedAccount() override;
|
||||||
|
void setSelectedAccountByIndex(int index) override;
|
||||||
|
void storeSelectedAccountAndLogin(QString password) override;
|
||||||
|
QString validateMnemonic(QString mnemonic) override;
|
||||||
|
void importMnemonic(QString mnemonic) override;
|
||||||
|
void onLogin(Signals::NodeSignal signal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Accounts::ServiceInterface* m_accountsService;
|
||||||
|
ModuleControllerDelegateInterface* m_delegate;
|
||||||
|
QString m_selectedAccountId;
|
||||||
|
};
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
|
||||||
|
// Abstract class for any input/interaction with this module.
|
||||||
|
|
||||||
|
class ControllerInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void init()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual QVector<Accounts::GeneratedAccountDto> getGeneratedAccounts()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual void setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual void storeSelectedAccountAndLogin(QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual Accounts::GeneratedAccountDto getImportedAccount()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual QString validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
virtual void importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "app_controller_delegate.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class ModuleControllerDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void setupAccountError()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void importAccountError()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void importAccountSuccess()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Onboarding
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void viewDidLoad()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void storeSelectedAccountAndLogin(QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Accounts::GeneratedAccountDto getImportedAccount()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Onboarding
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "item.h"
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
Item::Item(QString id, QString alias, QString identicon, QString address, QString keyUid)
|
||||||
|
: m_id(id)
|
||||||
|
, m_alias(alias)
|
||||||
|
, m_identicon(identicon)
|
||||||
|
, m_address(address)
|
||||||
|
, m_keyUid(keyUid)
|
||||||
|
{ }
|
||||||
|
QString Item::getId()
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
QString Item::getAlias()
|
||||||
|
{
|
||||||
|
return m_alias;
|
||||||
|
}
|
||||||
|
QString Item::getIdenticon()
|
||||||
|
{
|
||||||
|
return m_identicon;
|
||||||
|
}
|
||||||
|
QString Item::getAddress()
|
||||||
|
{
|
||||||
|
return m_address;
|
||||||
|
}
|
||||||
|
QString Item::getKeyUid()
|
||||||
|
{
|
||||||
|
return m_keyUid;
|
||||||
|
}
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class Item
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QString m_id;
|
||||||
|
QString m_alias;
|
||||||
|
QString m_identicon;
|
||||||
|
QString m_address;
|
||||||
|
QString m_keyUid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Item(QString id, QString alias, QString identicon, QString address, QString keyUid);
|
||||||
|
QString getId();
|
||||||
|
QString getAlias();
|
||||||
|
QString getIdenticon();
|
||||||
|
QString getAddress();
|
||||||
|
QString getKeyUid();
|
||||||
|
};
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "model.h"
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
Model::Model(QObject* parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
QHash<int, QByteArray> Model::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles[Id] = "accountId";
|
||||||
|
roles[Alias] = "username";
|
||||||
|
roles[Identicon] = "identicon";
|
||||||
|
roles[Address] = "address";
|
||||||
|
roles[KeyUid] = "keyUid";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Model::rowCount(const QModelIndex& parent = QModelIndex()) const
|
||||||
|
{
|
||||||
|
return m_items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant Model::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
if(!index.isValid())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index.row() < 0 || index.row() > m_items.size())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Item item = m_items[index.row()];
|
||||||
|
|
||||||
|
switch(role)
|
||||||
|
{
|
||||||
|
case Id: return QVariant(item.getId());
|
||||||
|
case Alias: return QVariant(item.getAlias());
|
||||||
|
case Identicon: return QVariant(item.getIdenticon());
|
||||||
|
case Address: return QVariant(item.getAddress());
|
||||||
|
case KeyUid: return QVariant(item.getKeyUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::setItems(QVector<Item> items)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_items = items;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QVector>
|
||||||
|
#include "item.h"
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class Model : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ModelRole
|
||||||
|
{
|
||||||
|
Id = Qt::UserRole + 1,
|
||||||
|
Alias = Qt::UserRole + 2,
|
||||||
|
Identicon = Qt::UserRole + 3,
|
||||||
|
Address = Qt::UserRole + 4,
|
||||||
|
KeyUid = Qt::UserRole + 5
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Model(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const;
|
||||||
|
virtual int rowCount(const QModelIndex&) const;
|
||||||
|
virtual QVariant data(const QModelIndex& index, int role) const;
|
||||||
|
void setItems(QVector<Item> items);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<Item> m_items;
|
||||||
|
};
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,101 @@
|
||||||
|
#include "module.h"
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "../interfaces/module_onboarding_delegate_interface.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "singleton.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlContext>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
Module::Module(Modules::Startup::ModuleOnboardingDelegateInterface* d, Accounts::ServiceInterface* accountsService)
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
m_controller = new Controller(this, accountsService);
|
||||||
|
m_view = new View(this);
|
||||||
|
m_moduleLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::~Module()
|
||||||
|
{
|
||||||
|
delete m_controller;
|
||||||
|
delete m_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::load()
|
||||||
|
{
|
||||||
|
Global::Singleton::instance()->engine()->rootContext()->setContextProperty("onboardingModule", m_view);
|
||||||
|
m_controller->init();
|
||||||
|
m_view->load();
|
||||||
|
|
||||||
|
QVector<Accounts::GeneratedAccountDto> gAcc = m_controller->getGeneratedAccounts();
|
||||||
|
QVector<Item> accounts;
|
||||||
|
foreach(const Accounts::GeneratedAccountDto& acc, gAcc)
|
||||||
|
{
|
||||||
|
accounts << Item(acc.id, acc.alias, acc.identicon, acc.address, acc.keyUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_view->setAccountList(accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Module::isLoaded()
|
||||||
|
{
|
||||||
|
return m_moduleLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::viewDidLoad()
|
||||||
|
{
|
||||||
|
m_moduleLoaded = true;
|
||||||
|
m_delegate->onboardingDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
m_controller->setSelectedAccountByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::storeSelectedAccountAndLogin(QString password)
|
||||||
|
{
|
||||||
|
m_controller->storeSelectedAccountAndLogin(password);
|
||||||
|
}
|
||||||
|
void Module::setupAccountError()
|
||||||
|
{
|
||||||
|
m_view->setupAccountError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::GeneratedAccountDto Module::getImportedAccount()
|
||||||
|
{
|
||||||
|
return m_controller->getImportedAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Module::validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
return m_controller->validateMnemonic(mnemonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
m_controller->importMnemonic(mnemonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::importAccountError()
|
||||||
|
{
|
||||||
|
m_view->importAccountError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::importAccountSuccess()
|
||||||
|
{
|
||||||
|
m_view->importAccountSuccess();
|
||||||
|
}
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../interfaces/module_onboarding_delegate_interface.h"
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "interfaces/module_controller_delegate_interface.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "module_access_interface.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class Module : public ModuleAccessInterface, ModuleControllerDelegateInterface, ModuleViewDelegateInterface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Modules::Startup::ModuleOnboardingDelegateInterface* m_delegate;
|
||||||
|
View* m_view;
|
||||||
|
Controller* m_controller;
|
||||||
|
bool m_moduleLoaded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Module(Modules::Startup::ModuleOnboardingDelegateInterface* d, Accounts::ServiceInterface* accountsService);
|
||||||
|
~Module();
|
||||||
|
void load() override;
|
||||||
|
bool isLoaded() override;
|
||||||
|
void viewDidLoad() override;
|
||||||
|
void setSelectedAccountByIndex(int index) override;
|
||||||
|
void storeSelectedAccountAndLogin(QString password) override;
|
||||||
|
void setupAccountError() override;
|
||||||
|
Accounts::GeneratedAccountDto getImportedAccount() override;
|
||||||
|
QString validateMnemonic(QString mnemonic) override;
|
||||||
|
void importMnemonic(QString mnemonic) override;
|
||||||
|
void importAccountError() override;
|
||||||
|
void importAccountSuccess() override;
|
||||||
|
};
|
||||||
|
}; // namespace Onboarding
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
class ModuleAccessInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void load()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isLoaded()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Onboarding
|
||||||
|
}; // namespace Startup
|
||||||
|
}; // namespace Modules
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include "view.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
View::View(ModuleViewDelegateInterface* d, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
m_model = new Model();
|
||||||
|
}
|
||||||
|
|
||||||
|
View::~View()
|
||||||
|
{
|
||||||
|
delete m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::load()
|
||||||
|
{
|
||||||
|
m_delegate->viewDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
Model* View::getModel()
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setAccountList(QVector<Item> accounts)
|
||||||
|
{
|
||||||
|
m_model->setItems(accounts);
|
||||||
|
View::modelChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString View::getImportedAccountIdenticon()
|
||||||
|
{
|
||||||
|
return m_delegate->getImportedAccount().identicon;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString View::getImportedAccountAlias()
|
||||||
|
{
|
||||||
|
return m_delegate->getImportedAccount().alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString View::getImportedAccountAddress()
|
||||||
|
{
|
||||||
|
return m_delegate->getImportedAccount().address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setSelectedAccountByIndex(int index)
|
||||||
|
{
|
||||||
|
m_delegate->setSelectedAccountByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::storeSelectedAccountAndLogin(QString password)
|
||||||
|
{
|
||||||
|
m_delegate->storeSelectedAccountAndLogin(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setupAccountError()
|
||||||
|
{
|
||||||
|
View::accountSetupError();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString View::validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
return m_delegate->validateMnemonic(mnemonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
m_delegate->importMnemonic(mnemonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::importAccountError()
|
||||||
|
{
|
||||||
|
// In QML we can connect to this signal and notify a user
|
||||||
|
// before refactoring we didn't have this signal
|
||||||
|
View::accountImportError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::importAccountSuccess()
|
||||||
|
{
|
||||||
|
View::importedAccountChanged();
|
||||||
|
}
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
namespace Onboarding
|
||||||
|
{
|
||||||
|
|
||||||
|
class View : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(Model* accountsModel READ getModel NOTIFY modelChanged)
|
||||||
|
Q_PROPERTY(QString importedAccountIdenticon READ getImportedAccountIdenticon NOTIFY importedAccountChanged)
|
||||||
|
Q_PROPERTY(QString importedAccountAlias READ getImportedAccountAlias NOTIFY importedAccountChanged)
|
||||||
|
Q_PROPERTY(QString importedAccountAddress READ getImportedAccountAddress NOTIFY importedAccountChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit View(ModuleViewDelegateInterface* d, QObject* parent = nullptr);
|
||||||
|
~View();
|
||||||
|
void load();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void modelChanged();
|
||||||
|
void importedAccountChanged();
|
||||||
|
void accountSetupError();
|
||||||
|
void accountImportError();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModuleViewDelegateInterface* m_delegate;
|
||||||
|
Model* m_model;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
Model* getModel();
|
||||||
|
void setAccountList(QVector<Item> accounts);
|
||||||
|
QString getImportedAccountIdenticon();
|
||||||
|
QString getImportedAccountAlias();
|
||||||
|
QString getImportedAccountAddress();
|
||||||
|
void setSelectedAccountByIndex(int index);
|
||||||
|
void storeSelectedAccountAndLogin(QString password);
|
||||||
|
QString validateMnemonic(QString mnemonic);
|
||||||
|
void importMnemonic(QString mnemonic);
|
||||||
|
void importAccountError();
|
||||||
|
void setupAccountError();
|
||||||
|
void importAccountSuccess();
|
||||||
|
};
|
||||||
|
} // namespace Onboarding
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "view.h"
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
|
||||||
|
View::View(ModuleViewDelegateInterface* d, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_appState(AppState::OnboardingState)
|
||||||
|
{
|
||||||
|
m_delegate = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::load()
|
||||||
|
{
|
||||||
|
// In some point, here, we will setup some exposed main module related things.
|
||||||
|
m_delegate->viewDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
int View::getAppState()
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_appState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setAppState(AppState state)
|
||||||
|
{
|
||||||
|
if(m_appState == state)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_appState = state;
|
||||||
|
appStateChanged(static_cast<int>(m_appState));
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::emitLogOut()
|
||||||
|
{
|
||||||
|
logOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interfaces/module_view_delegate_interface.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Modules
|
||||||
|
{
|
||||||
|
namespace Startup
|
||||||
|
{
|
||||||
|
enum AppState
|
||||||
|
{
|
||||||
|
OnboardingState = 0,
|
||||||
|
LoginState = 1,
|
||||||
|
MainAppState = 2
|
||||||
|
// TODO: is Pending
|
||||||
|
};
|
||||||
|
|
||||||
|
class View : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int appState READ getAppState NOTIFY appStateChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit View(ModuleViewDelegateInterface* d, QObject* parent = nullptr);
|
||||||
|
void emitLogOut();
|
||||||
|
void setAppState(AppState state);
|
||||||
|
void load();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void appStateChanged(int state);
|
||||||
|
void logOut();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModuleViewDelegateInterface* m_delegate;
|
||||||
|
AppState m_appState;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
int getAppState();
|
||||||
|
};
|
||||||
|
} // namespace Startup
|
||||||
|
} // namespace Modules
|
|
@ -0,0 +1,34 @@
|
||||||
|
add_library(app_service
|
||||||
|
constants.cpp
|
||||||
|
service/accounts/dto/account.cpp
|
||||||
|
service/accounts/dto/generated_account.cpp
|
||||||
|
service/accounts/service.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(app_service
|
||||||
|
PUBLIC
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
# default token is a free-tier token with limited capabilities and usage
|
||||||
|
# limits; setup your own infura key with
|
||||||
|
# cmake -DINFURA_KEY=infura_key_goes_here ..
|
||||||
|
if( "${INFURA_KEY}" STREQUAL "")
|
||||||
|
message("-- Using default Infura key")
|
||||||
|
file (STRINGS "../../resources/infura_key" INFURA_KEY)
|
||||||
|
else()
|
||||||
|
message("-- Using custom Infura key")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build constants
|
||||||
|
target_compile_definitions(app_service
|
||||||
|
PRIVATE
|
||||||
|
INFURA_KEY="${INFURA_KEY}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(app_service
|
||||||
|
PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
backend
|
||||||
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "constants.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
// TODO: merge with constants from backend/
|
||||||
|
|
||||||
|
|
||||||
|
QString Constants::applicationPath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Constants::tmpPath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Constants::cachePath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
class Image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString keyUid;
|
||||||
|
QString imgType;
|
||||||
|
QString uri;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int fileSize;
|
||||||
|
int resizeTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AccountDto
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString name;
|
||||||
|
long timestamp;
|
||||||
|
QString identicon;
|
||||||
|
QString keycardPairing;
|
||||||
|
QString keyUid;
|
||||||
|
QVector<Image> images;
|
||||||
|
|
||||||
|
bool isValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
Image toImage(const QJsonValue jsonObj);
|
||||||
|
|
||||||
|
AccountDto toAccountDto(const QJsonValue jsonObj);
|
||||||
|
} // namespace Accounts
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
class DerivedAccountDetails
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString publicKey;
|
||||||
|
QString address;
|
||||||
|
QString derivationPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivedAccounts
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DerivedAccountDetails whisper;
|
||||||
|
DerivedAccountDetails walletRoot;
|
||||||
|
DerivedAccountDetails defaultWallet;
|
||||||
|
DerivedAccountDetails eip1581;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GeneratedAccountDto
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString id;
|
||||||
|
QString publicKey;
|
||||||
|
QString address;
|
||||||
|
QString keyUid;
|
||||||
|
QString mnemonic;
|
||||||
|
DerivedAccounts derivedAccounts;
|
||||||
|
|
||||||
|
// The following two are set additionally.
|
||||||
|
QString alias;
|
||||||
|
QString identicon;
|
||||||
|
|
||||||
|
bool isValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
DerivedAccountDetails toDerivedAccountDetails(const QJsonValue jsonObj, QString derivationPath);
|
||||||
|
|
||||||
|
DerivedAccounts toDerivedAccounts(const QJsonObject jsonObj);
|
||||||
|
|
||||||
|
GeneratedAccountDto toGeneratedAccountDto(const QJsonValue jsonObj);
|
||||||
|
} // namespace Accounts
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "account.h"
|
||||||
|
#include "generated_account.h"
|
||||||
|
#include "service_interface.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
|
||||||
|
class Service : public ServiceInterface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QVector<GeneratedAccountDto> m_generatedAccounts;
|
||||||
|
|
||||||
|
bool m_isFirstTimeAccountLogin;
|
||||||
|
AccountDto m_loggedInAccount;
|
||||||
|
GeneratedAccountDto m_importedAccount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Service();
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
|
virtual QVector<AccountDto> openedAccounts() override;
|
||||||
|
|
||||||
|
QVector<GeneratedAccountDto> generatedAccounts() override;
|
||||||
|
|
||||||
|
bool setupAccount(QString accountId, QString password) override;
|
||||||
|
|
||||||
|
AccountDto getLoggedInAccount() override;
|
||||||
|
|
||||||
|
GeneratedAccountDto getImportedAccount() override;
|
||||||
|
|
||||||
|
bool isFirstTimeAccountLogin() override;
|
||||||
|
|
||||||
|
QString validateMnemonic(QString mnemonic) override;
|
||||||
|
|
||||||
|
bool importMnemonic(QString mnemonic) override;
|
||||||
|
|
||||||
|
QString login(AccountDto account, QString password) override;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
QString generateAlias(QString publicKey) override;
|
||||||
|
|
||||||
|
QString generateIdenticon(QString publicKey) override;
|
||||||
|
|
||||||
|
bool verifyAccountPassword(QString account, QString password) override;
|
||||||
|
|
||||||
|
DerivedAccounts storeDerivedAccounts(QString accountId, QString hashedPassword, QVector<QString> paths);
|
||||||
|
|
||||||
|
QJsonObject getAccountDataForAccountId(QString accountId);
|
||||||
|
|
||||||
|
QJsonArray getSubaccountDataForAccountId(QString accountId);
|
||||||
|
|
||||||
|
QJsonObject getAccountSettings(QString accountId, QString installationId);
|
||||||
|
|
||||||
|
QJsonObject getDefaultNodeConfig(QString installationId);
|
||||||
|
|
||||||
|
QJsonObject prepareAccountJsonObject(const GeneratedAccountDto account);
|
||||||
|
|
||||||
|
QJsonArray prepareSubaccountJsonObject(GeneratedAccountDto account);
|
||||||
|
|
||||||
|
QJsonObject prepareAccountSettingsJsonObject(const GeneratedAccountDto account, QString installationId);
|
||||||
|
|
||||||
|
AccountDto saveAccountAndLogin(
|
||||||
|
QString hashedPassword, QJsonObject account, QJsonArray subaccounts, QJsonObject settings, QJsonObject config);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Accounts
|
|
@ -0,0 +1,83 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../app_service.h"
|
||||||
|
#include "account.h"
|
||||||
|
#include "generated_account.h"
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
|
||||||
|
class ServiceInterface : public AppService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual QVector<AccountDto> openedAccounts()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVector<GeneratedAccountDto> generatedAccounts()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool setupAccount(QString accountId, QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual AccountDto getLoggedInAccount()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual GeneratedAccountDto getImportedAccount()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isFirstTimeAccountLogin()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString login(AccountDto account, QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void clear()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString generateAlias(QString publicKey)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QString generateIdenticon(QString publicKey)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool verifyAccountPassword(QString account, QString password)
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Accounts
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class AppService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void init()
|
||||||
|
{
|
||||||
|
throw std::domain_error("Not implemented");
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Constants
|
||||||
|
{
|
||||||
|
namespace Fleet
|
||||||
|
{
|
||||||
|
const QString Prod = "eth.prod";
|
||||||
|
const QString Staging = "eth.staging";
|
||||||
|
const QString Test = "eth.test";
|
||||||
|
const QString WakuV2Prod = "wakuv2.prod";
|
||||||
|
const QString WakuV2Test = "wakuv2.test";
|
||||||
|
const QString GoWakuTest = "go-waku.test";
|
||||||
|
}; // namespace Fleet
|
||||||
|
|
||||||
|
namespace FleetNodes
|
||||||
|
{
|
||||||
|
const QString Bootnodes = "boot";
|
||||||
|
const QString Mailservers = "mail";
|
||||||
|
const QString Rendezvous = "rendezvous";
|
||||||
|
const QString Whisper = "whisper";
|
||||||
|
const QString Waku = "waku";
|
||||||
|
const QString LibP2P = "libp2p";
|
||||||
|
const QString Websocket = "websocket";
|
||||||
|
} // namespace FleetNodes
|
||||||
|
|
||||||
|
const QString DefaultNetworkName = "mainnet_rpc";
|
||||||
|
//const DEFAULT_NETWORKS_IDS* = @["mainnet_rpc", "testnet_rpc", "rinkeby_rpc", "goerli_rpc", "xdai_rpc", "poa_rpc" ]
|
||||||
|
|
||||||
|
|
||||||
|
const QString DataDir = "/data";
|
||||||
|
const QString Keystore = "/data/keystore";
|
||||||
|
|
||||||
|
QString applicationPath(QString path = "");
|
||||||
|
QString tmpPath(QString path = "");
|
||||||
|
QString cachePath(QString path = "");
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Constants
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <QString>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
const std::array phrases{
|
||||||
|
"area", "army", "atom", "aunt", "babe", "baby", "back", "bail", "bait", "bake", "ball", "band", "bank", "barn", "base", "bass", "bath", "bead",
|
||||||
|
"beak", "beam", "bean", "bear", "beat", "beef", "beer", "beet", "bell", "belt", "bend", "bike", "bill", "bird", "bite", "blow", "blue", "boar",
|
||||||
|
"boat", "body", "bolt", "bomb", "bone", "book", "boot", "bore", "boss", "bowl", "brow", "bulb", "bull", "burn", "bush", "bust", "cafe", "cake",
|
||||||
|
"calf", "call", "calm", "camp", "cane", "cape", "card", "care", "carp", "cart", "case", "cash", "cast", "cave", "cell", "cent", "chap", "chef",
|
||||||
|
"chin", "chip", "chop", "chub", "chug", "city", "clam", "clef", "clip", "club", "clue", "coal", "coat", "code", "coil", "coin", "coke", "cold",
|
||||||
|
"colt", "comb", "cone", "cook", "cope", "copy", "cord", "cork", "corn", "cost", "crab", "craw", "crew", "crib", "crop", "crow", "curl", "cyst",
|
||||||
|
"dame", "dare", "dark", "dart", "dash", "data", "date", "dead", "deal", "dear", "debt", "deck", "deep", "deer", "desk", "dhow", "diet", "dill",
|
||||||
|
"dime", "dirt", "dish", "disk", "dock", "doll", "door", "dory", "drag", "draw", "drop", "drug", "drum", "duck", "dump", "dust", "duty", "ease",
|
||||||
|
"east", "eave", "eddy", "edge", "envy", "epee", "exam", "exit", "face", "fact", "fail", "fall", "fame", "fang", "farm", "fawn", "fear", "feed",
|
||||||
|
"feel", "feet", "file", "fill", "film", "find", "fine", "fire", "fish", "flag", "flat", "flax", "flow", "foam", "fold", "font", "food", "foot",
|
||||||
|
"fork", "form", "fort", "fowl", "frog", "fuel", "full", "gain", "gale", "galn", "game", "garb", "gate", "gear", "gene", "gift", "girl", "give",
|
||||||
|
"glad", "glen", "glue", "glut", "goal", "goat", "gold", "golf", "gong", "good", "gown", "grab", "gram", "gray", "grey", "grip", "grit", "gyro",
|
||||||
|
"hail", "hair", "half", "hall", "hand", "hang", "harm", "harp", "hate", "hawk", "head", "heat", "heel", "hell", "helo", "help", "hemp", "herb",
|
||||||
|
"hide", "high", "hill", "hire", "hive", "hold", "hole", "home", "hood", "hoof", "hook", "hope", "hops", "horn", "hose", "host", "hour", "hunt",
|
||||||
|
"hurt", "icon", "idea", "inch", "iris", "iron", "item", "jail", "jeep", "jeff", "joey", "join", "joke", "judo", "jump", "junk", "jury", "jute",
|
||||||
|
"kale", "keep", "kick", "kill", "kilt", "kind", "king", "kiss", "kite", "knee", "knot", "lace", "lack", "lady", "lake", "lamb", "lamp", "land",
|
||||||
|
"lark", "lava", "lawn", "lead", "leaf", "leek", "lier", "life", "lift", "lily", "limo", "line", "link", "lion", "lisa", "list", "load", "loaf",
|
||||||
|
"loan", "lock", "loft", "long", "look", "loss", "lout", "love", "luck", "lung", "lute", "lynx", "lyre", "maid", "mail", "main", "make", "male",
|
||||||
|
"mall", "manx", "many", "mare", "mark", "mask", "mass", "mate", "math", "meal", "meat", "meet", "menu", "mess", "mice", "midi", "mile", "milk",
|
||||||
|
"mime", "mind", "mine", "mini", "mint", "miss", "mist", "moat", "mode", "mole", "mood", "moon", "most", "moth", "move", "mule", "mutt", "nail",
|
||||||
|
"name", "neat", "neck", "need", "neon", "nest", "news", "node", "nose", "note", "oboe", "okra", "open", "oval", "oven", "oxen", "pace", "pack",
|
||||||
|
"page", "pail", "pain", "pair", "palm", "pard", "park", "part", "pass", "past", "path", "peak", "pear", "peen", "peer", "pelt", "perp", "pest",
|
||||||
|
"pick", "pier", "pike", "pile", "pimp", "pine", "ping", "pink", "pint", "pipe", "piss", "pith", "plan", "play", "plot", "plow", "poem", "poet",
|
||||||
|
"pole", "polo", "pond", "pony", "poof", "pool", "port", "post", "prow", "pull", "puma", "pump", "pupa", "push", "quit", "race", "rack", "raft",
|
||||||
|
"rage", "rail", "rain", "rake", "rank", "rate", "read", "rear", "reef", "rent", "rest", "rice", "rich", "ride", "ring", "rise", "risk", "road",
|
||||||
|
"robe", "rock", "role", "roll", "roof", "room", "root", "rope", "rose", "ruin", "rule", "rush", "ruth", "sack", "safe", "sage", "sail", "sale",
|
||||||
|
"salt", "sand", "sari", "sash", "save", "scow", "seal", "seat", "seed", "self", "sell", "shed", "shin", "ship", "shoe", "shop", "shot", "show",
|
||||||
|
"sick", "side", "sign", "silk", "sill", "silo", "sing", "sink", "site", "size", "skin", "sled", "slip", "smog", "snob", "snow", "soap", "sock",
|
||||||
|
"soda", "sofa", "soft", "soil", "song", "soot", "sort", "soup", "spot", "spur", "stag", "star", "stay", "stem", "step", "stew", "stop", "stud",
|
||||||
|
"suck", "suit", "swan", "swim", "tail", "tale", "talk", "tank", "tard", "task", "taxi", "team", "tear", "teen", "tell", "temp", "tent", "term",
|
||||||
|
"test", "text", "thaw", "tile", "till", "time", "tire", "toad", "toga", "togs", "tone", "tool", "toot", "tote", "tour", "town", "tram", "tray",
|
||||||
|
"tree", "trim", "trip", "tuba", "tube", "tuna", "tune", "turn", "tutu", "twig", "type", "unit", "user", "vane", "vase", "vast", "veal", "veil",
|
||||||
|
"vein", "vest", "vibe", "view", "vise", "wait", "wake", "walk", "wall", "wash", "wasp", "wave", "wear", "weed", "week", "well", "west", "whip",
|
||||||
|
"wife", "will", "wind", "wine", "wing", "wire", "wish", "wolf", "wood", "wool", "word", "work", "worm", "wrap", "wren", "yard", "yarn", "yawl",
|
||||||
|
"year", "yoga", "yoke", "yurt", "zinc", "zone"};
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "accounts/account.h"
|
||||||
|
#include "backend/accounts.h"
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
bool Accounts::AccountDto::isValid()
|
||||||
|
{
|
||||||
|
return name.length() > 0 && keyUid.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::Image Accounts::toImage(const QJsonValue jsonObj)
|
||||||
|
{
|
||||||
|
auto result = Accounts::Image();
|
||||||
|
|
||||||
|
result.keyUid = jsonObj["keyUid"].toString();
|
||||||
|
result.imgType = jsonObj["type"].toString();
|
||||||
|
result.uri = jsonObj["uri"].toString();
|
||||||
|
result.width = jsonObj["width"].toInt();
|
||||||
|
result.height = jsonObj["height"].toInt();
|
||||||
|
result.fileSize = jsonObj["fileSize"].toInt();
|
||||||
|
result.resizeTarget = jsonObj["resizeTarget"].toInt();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::AccountDto Accounts::toAccountDto(const QJsonValue jsonObj)
|
||||||
|
{
|
||||||
|
auto result = Accounts::AccountDto();
|
||||||
|
|
||||||
|
result.name = jsonObj["name"].toString();
|
||||||
|
result.timestamp = jsonObj["timestamp"].toInt();
|
||||||
|
result.identicon = jsonObj["identicon"].toString();
|
||||||
|
result.keycardPairing = jsonObj["keycard-pairing"].toString();
|
||||||
|
result.keyUid = jsonObj["key-uid"].toString();
|
||||||
|
|
||||||
|
foreach(const QJsonValue& value, jsonObj["images"].toArray())
|
||||||
|
{
|
||||||
|
result.images << Accounts::toImage(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "backend/accounts.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
bool Accounts::GeneratedAccountDto::isValid()
|
||||||
|
{
|
||||||
|
return id.length() > 0 && publicKey.length() > 0 && address.length() > 0 && keyUid.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::DerivedAccountDetails Accounts::toDerivedAccountDetails(const QJsonValue jsonObj, QString derivationPath)
|
||||||
|
{
|
||||||
|
// Mapping this DTO is not strightforward since only keys are used for id. We
|
||||||
|
// handle it a bit different.
|
||||||
|
auto result = Accounts::DerivedAccountDetails();
|
||||||
|
|
||||||
|
result.derivationPath = derivationPath;
|
||||||
|
result.publicKey = jsonObj["publicKey"].toString();
|
||||||
|
result.address = jsonObj["address"].toString();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::DerivedAccounts Accounts::toDerivedAccounts(const QJsonObject jsonObj)
|
||||||
|
{
|
||||||
|
auto result = Accounts::DerivedAccounts();
|
||||||
|
foreach(const QString& derivationPath, jsonObj.keys())
|
||||||
|
{
|
||||||
|
QJsonValue derivedObj = jsonObj.value(derivationPath);
|
||||||
|
if(derivationPath == Backend::Accounts::PATH_WHISPER)
|
||||||
|
{
|
||||||
|
result.whisper = Accounts::toDerivedAccountDetails(derivedObj, derivationPath);
|
||||||
|
}
|
||||||
|
else if(derivationPath == Backend::Accounts::PATH_WALLET_ROOT)
|
||||||
|
{
|
||||||
|
result.walletRoot = Accounts::toDerivedAccountDetails(derivedObj, derivationPath);
|
||||||
|
}
|
||||||
|
else if(derivationPath == Backend::Accounts::PATH_DEFAULT_WALLET)
|
||||||
|
{
|
||||||
|
result.defaultWallet = Accounts::toDerivedAccountDetails(derivedObj, derivationPath);
|
||||||
|
}
|
||||||
|
else if(derivationPath == Backend::Accounts::PATH_EIP_1581)
|
||||||
|
{
|
||||||
|
result.eip1581 = Accounts::toDerivedAccountDetails(derivedObj, derivationPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::GeneratedAccountDto Accounts::toGeneratedAccountDto(const QJsonValue jsonObj)
|
||||||
|
{
|
||||||
|
auto result = GeneratedAccountDto();
|
||||||
|
|
||||||
|
result.id = jsonObj["id"].toString();
|
||||||
|
result.address = jsonObj["address"].toString();
|
||||||
|
result.keyUid = jsonObj["keyUid"].toString();
|
||||||
|
result.mnemonic = jsonObj["mnemonic"].toString();
|
||||||
|
result.publicKey = jsonObj["publicKey"].toString();
|
||||||
|
if(!jsonObj["derived"].isUndefined())
|
||||||
|
{
|
||||||
|
result.derivedAccounts = Accounts::toDerivedAccounts(jsonObj["derived"].toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,374 @@
|
||||||
|
#include "accounts/service.h"
|
||||||
|
#include "accounts/account.h"
|
||||||
|
#include "accounts/generated_account.h"
|
||||||
|
#include "accounts/service_interface.h"
|
||||||
|
#include "app_service.h"
|
||||||
|
#include "backend/accounts.h"
|
||||||
|
#include "backend/utils.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "signing-phrases.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
|
||||||
|
Service::Service()
|
||||||
|
: m_isFirstTimeAccountLogin(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
const QVector<QString> PATHS{Backend::Accounts::PATH_WALLET_ROOT,
|
||||||
|
Backend::Accounts::PATH_EIP_1581,
|
||||||
|
Backend::Accounts::PATH_WHISPER,
|
||||||
|
Backend::Accounts::PATH_DEFAULT_WALLET};
|
||||||
|
|
||||||
|
void Service::init()
|
||||||
|
{
|
||||||
|
auto response = Backend::Accounts::generateAddresses(Accounts::PATHS);
|
||||||
|
foreach(QJsonValue generatedAddressJson, response.m_result)
|
||||||
|
{
|
||||||
|
auto gAcc = toGeneratedAccountDto(generatedAddressJson);
|
||||||
|
gAcc.alias = generateAlias(gAcc.derivedAccounts.whisper.publicKey);
|
||||||
|
gAcc.identicon = generateIdenticon(gAcc.derivedAccounts.whisper.publicKey);
|
||||||
|
m_generatedAccounts << gAcc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<AccountDto> Service::openedAccounts()
|
||||||
|
{
|
||||||
|
// try
|
||||||
|
auto response = Backend::Accounts::openAccounts(Constants::applicationPath(Constants::DataDir));
|
||||||
|
QJsonArray multiAccounts = response.m_result;
|
||||||
|
QVector<AccountDto> result;
|
||||||
|
foreach(const QJsonValue& value, multiAccounts)
|
||||||
|
{
|
||||||
|
result << toAccountDto(value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
//} catch(const std::exception& e){
|
||||||
|
// error "error: ", methodName="openedAccounts", errName = e.name, errDesription = e.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<GeneratedAccountDto> Service::generatedAccounts()
|
||||||
|
{
|
||||||
|
if(m_generatedAccounts.length() == 0)
|
||||||
|
{
|
||||||
|
qWarning("There was some issue initiating account service");
|
||||||
|
return QVector<GeneratedAccountDto>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_generatedAccounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::setupAccount(QString accountId, QString password)
|
||||||
|
{
|
||||||
|
//try:
|
||||||
|
QString installationId(QUuid::createUuid().toString(QUuid::WithoutBraces));
|
||||||
|
QJsonObject accountData(Service::getAccountDataForAccountId(accountId));
|
||||||
|
QJsonArray subAccountData(Service::getSubaccountDataForAccountId(accountId));
|
||||||
|
QJsonObject settings(Service::getAccountSettings(accountId, installationId));
|
||||||
|
QJsonObject nodeConfig(Service::getDefaultNodeConfig(installationId));
|
||||||
|
|
||||||
|
// if(accountDataJson.isNil or subaccountDataJson.isNil or settingsJson.isNil or
|
||||||
|
// nodeConfigJson.isNil):
|
||||||
|
//let description = "at least one json object is not prepared well"
|
||||||
|
//error "error: ", methodName="setupAccount", errDesription = description
|
||||||
|
//return false
|
||||||
|
|
||||||
|
QString hashedPassword(Backend::Utils::hashString(password));
|
||||||
|
|
||||||
|
Service::storeDerivedAccounts(accountId, hashedPassword, PATHS);
|
||||||
|
|
||||||
|
m_loggedInAccount = Service::saveAccountAndLogin(hashedPassword, accountData, subAccountData, settings, nodeConfig);
|
||||||
|
|
||||||
|
return Service::getLoggedInAccount().isValid();
|
||||||
|
|
||||||
|
//except Exception as e:
|
||||||
|
// error "error: ", methodName="setupAccount", errName = e.name, errDesription = e.msg
|
||||||
|
//return false*/
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountDto Service::getLoggedInAccount()
|
||||||
|
{
|
||||||
|
return m_loggedInAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratedAccountDto Service::getImportedAccount()
|
||||||
|
{
|
||||||
|
return m_importedAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::isFirstTimeAccountLogin()
|
||||||
|
{
|
||||||
|
return m_isFirstTimeAccountLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Service::validateMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::importMnemonic(QString mnemonic)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Service::login(AccountDto account, QString password)
|
||||||
|
{
|
||||||
|
//try:
|
||||||
|
QString hashedPassword(Backend::Utils::hashString(password));
|
||||||
|
|
||||||
|
QString thumbnailImage;
|
||||||
|
QString largeImage;
|
||||||
|
|
||||||
|
foreach(const Accounts::Image& img, account.images)
|
||||||
|
{
|
||||||
|
if(img.imgType == "thumbnail")
|
||||||
|
{
|
||||||
|
thumbnailImage = img.uri;
|
||||||
|
}
|
||||||
|
else if(img.imgType == "large")
|
||||||
|
{
|
||||||
|
largeImage = img.uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto response = Backend::Accounts::login(
|
||||||
|
account.name, account.keyUid, hashedPassword, account.identicon, thumbnailImage, largeImage);
|
||||||
|
// TODO: check response for errors
|
||||||
|
|
||||||
|
qDebug() << "Account logged in";
|
||||||
|
|
||||||
|
m_loggedInAccount = account;
|
||||||
|
|
||||||
|
return "";
|
||||||
|
|
||||||
|
//except Exception as e:
|
||||||
|
//error "error: ", methodName="setupAccount", errName = e.name, errDesription = e.msg
|
||||||
|
//return e.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::clear()
|
||||||
|
{
|
||||||
|
m_generatedAccounts.clear();
|
||||||
|
m_loggedInAccount = Accounts::AccountDto();
|
||||||
|
m_importedAccount = Accounts::GeneratedAccountDto();
|
||||||
|
m_isFirstTimeAccountLogin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Service::generateAlias(QString publicKey)
|
||||||
|
{
|
||||||
|
return Backend::Accounts::generateAlias(publicKey).m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Service::generateIdenticon(QString publicKey)
|
||||||
|
{
|
||||||
|
return Backend::Accounts::generateIdenticon(publicKey).m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::verifyAccountPassword(QString account, QString password)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedAccounts Service::storeDerivedAccounts(QString accountId, QString hashedPassword, QVector<QString> paths)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto response = Backend::Accounts::storeDerivedAccounts(accountId, hashedPassword, paths);
|
||||||
|
return toDerivedAccounts(response.m_result);
|
||||||
|
}
|
||||||
|
catch(Backend::RpcException& e)
|
||||||
|
{
|
||||||
|
qWarning() << e.what();
|
||||||
|
return DerivedAccounts(); // TODO: should it return empty?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Accounts::AccountDto Service::saveAccountAndLogin(
|
||||||
|
QString hashedPassword, QJsonObject account, QJsonArray subaccounts, QJsonObject settings, QJsonObject config)
|
||||||
|
{
|
||||||
|
//try:
|
||||||
|
auto response = Backend::Accounts::saveAccountAndLogin(hashedPassword, account, subaccounts, settings, config);
|
||||||
|
|
||||||
|
m_isFirstTimeAccountLogin = true;
|
||||||
|
return toAccountDto(account);
|
||||||
|
|
||||||
|
// except Exception as e:
|
||||||
|
// error "error: ", methodName="saveAccountAndLogin", errName = e.name, errDesription = e.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Service::prepareAccountJsonObject(const GeneratedAccountDto account)
|
||||||
|
{
|
||||||
|
return QJsonObject{{"name", account.alias},
|
||||||
|
{"address", account.address},
|
||||||
|
{"photo-path", account.identicon},
|
||||||
|
{"identicon", account.identicon},
|
||||||
|
{"key-uid", account.keyUid},
|
||||||
|
{"keycard-pairing", QJsonValue()}};
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Service::getAccountDataForAccountId(QString accountId)
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach(const GeneratedAccountDto& acc, m_generatedAccounts)
|
||||||
|
{
|
||||||
|
if(acc.id == accountId)
|
||||||
|
{
|
||||||
|
return Service::prepareAccountJsonObject(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_importedAccount.isValid())
|
||||||
|
{
|
||||||
|
if(m_importedAccount.id == accountId)
|
||||||
|
{
|
||||||
|
return Service::prepareAccountJsonObject(m_importedAccount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray Service::prepareSubaccountJsonObject(GeneratedAccountDto account)
|
||||||
|
{
|
||||||
|
return QJsonArray{QJsonObject{{"public-key", account.derivedAccounts.defaultWallet.publicKey},
|
||||||
|
{"address", account.derivedAccounts.defaultWallet.address},
|
||||||
|
{"color", "#4360df"},
|
||||||
|
{"wallet", true},
|
||||||
|
{"path", Backend::Accounts::PATH_DEFAULT_WALLET},
|
||||||
|
{"name", "Status account"}},
|
||||||
|
QJsonObject{{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||||
|
{"address", account.derivedAccounts.whisper.address},
|
||||||
|
{"path", Backend::Accounts::PATH_WHISPER},
|
||||||
|
{"name", account.alias},
|
||||||
|
{"identicon", account.identicon},
|
||||||
|
{"chat", true}}};
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray Service::getSubaccountDataForAccountId(QString accountId)
|
||||||
|
{
|
||||||
|
foreach(const GeneratedAccountDto& acc, m_generatedAccounts)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(acc.id == accountId)
|
||||||
|
{
|
||||||
|
return prepareSubaccountJsonObject(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m_importedAccount.isValid())
|
||||||
|
{
|
||||||
|
if(m_importedAccount.id == accountId)
|
||||||
|
{
|
||||||
|
return prepareSubaccountJsonObject(m_importedAccount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString generateSigningPhrase(int count)
|
||||||
|
{
|
||||||
|
QStringList words;
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
words.append(phrases[QRandomGenerator::global()->bounded(static_cast<int>(phrases.size()))]);
|
||||||
|
}
|
||||||
|
return words.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Service::prepareAccountSettingsJsonObject(const GeneratedAccountDto account, QString installationId)
|
||||||
|
{
|
||||||
|
QFile defaultNetworks(":/resources/default-networks.json");
|
||||||
|
defaultNetworks.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
QString defaultNetworksContent = defaultNetworks.readAll().replace("%INFURA_KEY%", INFURA_KEY);
|
||||||
|
QJsonArray defaultNetworksJson = QJsonDocument::fromJson(defaultNetworksContent.toUtf8()).array();
|
||||||
|
|
||||||
|
return QJsonObject{{"key-uid", account.keyUid},
|
||||||
|
{"mnemonic", account.mnemonic},
|
||||||
|
{"public-key", account.derivedAccounts.whisper.publicKey},
|
||||||
|
{"name", account.alias},
|
||||||
|
{"address", account.address},
|
||||||
|
{"eip1581-address", account.derivedAccounts.eip1581.address},
|
||||||
|
{"dapps-address", account.derivedAccounts.defaultWallet.address},
|
||||||
|
{"wallet-root-address", account.derivedAccounts.walletRoot.address},
|
||||||
|
{"preview-privacy?", true},
|
||||||
|
{"signing-phrase", generateSigningPhrase(3)},
|
||||||
|
{"log-level", "INFO"},
|
||||||
|
{"latest-derived-path", 0},
|
||||||
|
{"networks/networks", defaultNetworksJson},
|
||||||
|
{"currency", "usd"},
|
||||||
|
{"identicon", account.identicon},
|
||||||
|
{"waku-enabled", true},
|
||||||
|
{"wallet/visible-tokens", {{Constants::DefaultNetworkName, QJsonArray{"SNT"}}}},
|
||||||
|
{"appearance", 0},
|
||||||
|
{"networks/current-network", Constants::DefaultNetworkName},
|
||||||
|
{"installation-id", installationId}};
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Service::getAccountSettings(QString accountId, QString installationId)
|
||||||
|
{
|
||||||
|
foreach(const GeneratedAccountDto& acc, m_generatedAccounts)
|
||||||
|
|
||||||
|
if(acc.id == accountId)
|
||||||
|
{
|
||||||
|
return Service::prepareAccountSettingsJsonObject(acc, installationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_importedAccount.isValid())
|
||||||
|
{
|
||||||
|
if(m_importedAccount.id == accountId)
|
||||||
|
{
|
||||||
|
return Service::prepareAccountSettingsJsonObject(m_importedAccount, installationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray getNodes(const QJsonObject fleet, QString nodeType)
|
||||||
|
{
|
||||||
|
auto nodes = fleet[nodeType].toObject();
|
||||||
|
QJsonArray result;
|
||||||
|
for(auto it = nodes.begin(); it != nodes.end(); ++it)
|
||||||
|
result << *it;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject Service::getDefaultNodeConfig(QString installationId)
|
||||||
|
{
|
||||||
|
QFile nodeConfig(":/resources/node-config.json");
|
||||||
|
nodeConfig.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
QString nodeConfigContent = nodeConfig.readAll();
|
||||||
|
|
||||||
|
nodeConfigContent = nodeConfigContent.replace("%INSTALLATIONID%", installationId);
|
||||||
|
nodeConfigContent = nodeConfigContent.replace("%INFURA_KEY%", INFURA_KEY);
|
||||||
|
|
||||||
|
QJsonObject nodeConfigJson = QJsonDocument::fromJson(nodeConfigContent.toUtf8()).object();
|
||||||
|
|
||||||
|
QFile fleets(":/resources/fleets.json");
|
||||||
|
fleets.open(QIODevice::ReadOnly);
|
||||||
|
QJsonObject fleetsJson = QJsonDocument::fromJson(fleets.readAll()).object()["fleets"].toObject();
|
||||||
|
|
||||||
|
auto fleet = fleetsJson[Constants::Fleet::Prod].toObject();
|
||||||
|
|
||||||
|
QJsonObject clusterConfig = nodeConfigJson["ClusterConfig"].toObject();
|
||||||
|
|
||||||
|
clusterConfig["Fleet"] = Constants::Fleet::Prod;
|
||||||
|
clusterConfig["BootNodes"] = getNodes(fleet, Constants::FleetNodes::Bootnodes);
|
||||||
|
clusterConfig["TrustedMailServers"] = getNodes(fleet, Constants::FleetNodes::Mailservers);
|
||||||
|
clusterConfig["StaticNodes"] = getNodes(fleet, Constants::FleetNodes::Whisper);
|
||||||
|
clusterConfig["RendezvousNodes"] = getNodes(fleet, Constants::FleetNodes::Rendezvous);
|
||||||
|
clusterConfig["RelayNodes"] = getNodes(fleet, Constants::FleetNodes::Waku);
|
||||||
|
clusterConfig["StoreNodes"] = getNodes(fleet, Constants::FleetNodes::Waku);
|
||||||
|
clusterConfig["FilterNodes"] = getNodes(fleet, Constants::FleetNodes::Waku);
|
||||||
|
clusterConfig["LightpushNodes"] = getNodes(fleet, Constants::FleetNodes::Waku);
|
||||||
|
|
||||||
|
nodeConfigJson["ClusterConfig"] = clusterConfig;
|
||||||
|
|
||||||
|
return nodeConfigJson;
|
||||||
|
}
|
||||||
|
} // namespace Accounts
|
|
@ -0,0 +1,18 @@
|
||||||
|
add_library(backend
|
||||||
|
accounts.cpp
|
||||||
|
types.cpp
|
||||||
|
utils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(backend
|
||||||
|
PUBLIC
|
||||||
|
include/
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(backend
|
||||||
|
PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
statusgo_shared
|
||||||
|
|
||||||
|
)
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "backend/accounts.h"
|
||||||
|
#include "backend/types.h"
|
||||||
|
#include "backend/utils.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
#include "libstatus.h"
|
||||||
|
|
||||||
|
const int NUMBER_OF_ADDRESSES_TO_GENERATE = 5;
|
||||||
|
const int MNEMONIC_PHRASE_LENGTH = 12;
|
||||||
|
|
||||||
|
Backend::RpcResponse<QJsonArray> Backend::Accounts::generateAddresses(QVector<QString> paths)
|
||||||
|
{
|
||||||
|
QJsonObject payload{{"n", NUMBER_OF_ADDRESSES_TO_GENERATE},
|
||||||
|
{"mnemonicPhraseLength", MNEMONIC_PHRASE_LENGTH},
|
||||||
|
{"bip32Passphrase", ""},
|
||||||
|
{"paths", Utils::toJsonArray(paths)}
|
||||||
|
|
||||||
|
};
|
||||||
|
const char* result = MultiAccountGenerateAndDeriveAddresses(Utils::jsonToStr(payload).toUtf8().data());
|
||||||
|
return Backend::RpcResponse<QJsonArray>(result, QJsonDocument::fromJson(result).array());
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QString> Backend::Accounts::generateIdenticon(QString publicKey)
|
||||||
|
{
|
||||||
|
if(!publicKey.isEmpty())
|
||||||
|
{
|
||||||
|
auto identicon = QString(Identicon(publicKey.toUtf8().data()));
|
||||||
|
return Backend::RpcResponse<QString>(identicon, identicon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw Backend::RpcException("publicKey can't be empty1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QString> Backend::Accounts::generateAlias(QString publicKey)
|
||||||
|
{
|
||||||
|
if(!publicKey.isEmpty())
|
||||||
|
{
|
||||||
|
auto alias = QString(GenerateAlias(publicKey.toUtf8().data()));
|
||||||
|
return Backend::RpcResponse<QString>(alias, alias);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw Backend::RpcException("publicKey can't be empty2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QJsonObject>
|
||||||
|
Backend::Accounts::storeDerivedAccounts(QString id, QString hashedPassword, QVector<QString> paths)
|
||||||
|
{
|
||||||
|
QJsonObject payload{{"accountID", id}, {"paths", Utils::toJsonArray(paths)}, {"password", hashedPassword}};
|
||||||
|
auto result = MultiAccountStoreDerivedAccounts(Utils::jsonToStr(payload).toUtf8().data());
|
||||||
|
auto obj = QJsonDocument::fromJson(result).object();
|
||||||
|
Backend::Utils::throwOnError(obj);
|
||||||
|
return Backend::RpcResponse<QJsonObject>(result, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QJsonObject> Backend::Accounts::saveAccountAndLogin(
|
||||||
|
QString hashedPassword, QJsonObject account, QJsonArray subaccounts, QJsonObject settings, QJsonObject nodeConfig)
|
||||||
|
{
|
||||||
|
auto result = SaveAccountAndLogin(Utils::jsonToStr(account).toUtf8().data(),
|
||||||
|
hashedPassword.toUtf8().data(),
|
||||||
|
Utils::jsonToStr(settings).toUtf8().data(),
|
||||||
|
Utils::jsonToStr(nodeConfig).toUtf8().data(),
|
||||||
|
Utils::jsonToStr(subaccounts).toUtf8().data());
|
||||||
|
auto obj = QJsonDocument::fromJson(result).object();
|
||||||
|
Backend::Utils::throwOnError(obj);
|
||||||
|
return Backend::RpcResponse<QJsonObject>(result, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QJsonArray> Backend::Accounts::openAccounts(QString path)
|
||||||
|
{
|
||||||
|
const char* result = OpenAccounts(path.toUtf8().data());
|
||||||
|
auto resp = Backend::RpcResponse<QJsonArray>(result, QJsonDocument::fromJson(result).array());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcResponse<QJsonObject> Backend::Accounts::login(
|
||||||
|
QString name, QString keyUid, QString hashedPassword, QString identicon, QString thumbnail, QString large)
|
||||||
|
{
|
||||||
|
QJsonObject payload{{"name", name}, {"key-uid", keyUid}, {"identityImage", QJsonValue()}, {"identicon", identicon}};
|
||||||
|
|
||||||
|
if(!thumbnail.isEmpty() && !large.isEmpty())
|
||||||
|
{
|
||||||
|
payload["identityImage"] = QJsonObject{{"thumbnail", thumbnail}, {"large", large}};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = Login(Utils::jsonToStr(payload).toUtf8().data(), hashedPassword.toUtf8().data());
|
||||||
|
auto obj = QJsonDocument::fromJson(result).object();
|
||||||
|
Backend::Utils::throwOnError(obj);
|
||||||
|
return Backend::RpcResponse<QJsonObject>(result, obj);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "backend/types.h"
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Backend
|
||||||
|
{
|
||||||
|
namespace Accounts
|
||||||
|
{
|
||||||
|
const QString ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||||
|
|
||||||
|
const QString PATH_WALLET_ROOT = "m/44'/60'/0'/0";
|
||||||
|
// EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived
|
||||||
|
const QString PATH_EIP_1581 = "m/43'/60'/1581'";
|
||||||
|
// BIP44-0 Wallet key, the default wallet key
|
||||||
|
const QString PATH_DEFAULT_WALLET = PATH_WALLET_ROOT + "/0";
|
||||||
|
// EIP1581 Chat Key 0, the default whisper key
|
||||||
|
const QString PATH_WHISPER = PATH_EIP_1581 + "/0'/0";
|
||||||
|
|
||||||
|
RpcResponse<QJsonArray> generateAddresses(QVector<QString> paths);
|
||||||
|
|
||||||
|
RpcResponse<QString> generateIdenticon(QString publicKey);
|
||||||
|
|
||||||
|
RpcResponse<QString> generateAlias(QString publicKey);
|
||||||
|
|
||||||
|
RpcResponse<QJsonObject> storeDerivedAccounts(QString accountId, QString hashedPassword, QVector<QString> paths);
|
||||||
|
|
||||||
|
RpcResponse<QJsonObject> saveAccountAndLogin(
|
||||||
|
QString hashedPassword, QJsonObject account, QJsonArray subaccounts, QJsonObject settings, QJsonObject nodeConfig);
|
||||||
|
|
||||||
|
RpcResponse<QJsonArray> openAccounts(QString path);
|
||||||
|
|
||||||
|
RpcResponse<QJsonObject>
|
||||||
|
login(QString name, QString keyUid, QString hashedPassword, QString identicon, QString thumbnail, QString large);
|
||||||
|
|
||||||
|
} // namespace Accounts
|
||||||
|
} // namespace Backend
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Backend
|
||||||
|
{
|
||||||
|
|
||||||
|
const QString GENERATED = "generated";
|
||||||
|
const QString SEED = "seed";
|
||||||
|
const QString KEY = "key";
|
||||||
|
const QString WATCH = "watch";
|
||||||
|
|
||||||
|
struct RpcException : public std::exception
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string m_message;
|
||||||
|
public:
|
||||||
|
explicit RpcException(const std::string& message);
|
||||||
|
const char* what() const throw();
|
||||||
|
};
|
||||||
|
|
||||||
|
class RpcError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int m_code;
|
||||||
|
QString m_message;
|
||||||
|
|
||||||
|
friend ostream& operator<<(ostream& os, Backend::RpcError& r);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
class RpcResponse
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString m_jsonrpc;
|
||||||
|
T m_result;
|
||||||
|
int m_id;
|
||||||
|
RpcError m_error;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RpcResponse(QString jsonrpc, T result)
|
||||||
|
: m_jsonrpc(jsonrpc)
|
||||||
|
, m_result(result)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Backend
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace Backend
|
||||||
|
{
|
||||||
|
class Utils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static QString hashString(QString str);
|
||||||
|
static QString jsonToStr(QJsonObject obj);
|
||||||
|
static QString jsonToStr(QJsonArray arr);
|
||||||
|
static QJsonArray toJsonArray(const QVector<QString>& value);
|
||||||
|
static QVector<QString> toStringVector(const QJsonArray& arr);
|
||||||
|
static void throwOnError(QJsonObject response);
|
||||||
|
};
|
||||||
|
} // namespace Backend
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include "backend/types.h"
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
ostream& operator<<(ostream& os, const Backend::RpcError& r)
|
||||||
|
{
|
||||||
|
return (os << "RpcError(\n code: " << r.m_code << "\n message: " << r.m_message.toStdString() << "\n)"
|
||||||
|
<< std::endl);
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend::RpcException::RpcException(const std::string& message)
|
||||||
|
: m_message(message)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
const char* Backend::RpcException::what() const throw()
|
||||||
|
{
|
||||||
|
return m_message.c_str();
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "backend/utils.h"
|
||||||
|
#include "backend/types.h"
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
QJsonArray Backend::Utils::toJsonArray(const QVector<QString>& value)
|
||||||
|
{
|
||||||
|
QJsonArray array;
|
||||||
|
for(auto& v : value)
|
||||||
|
array << v;
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Backend::Utils::jsonToStr(QJsonObject obj)
|
||||||
|
{
|
||||||
|
QJsonDocument doc(obj);
|
||||||
|
return QString::fromUtf8(doc.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Backend::Utils::jsonToStr(QJsonArray arr)
|
||||||
|
{
|
||||||
|
QJsonDocument doc(arr);
|
||||||
|
return QString::fromUtf8(doc.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> Backend::Utils::toStringVector(const QJsonArray& arr)
|
||||||
|
{
|
||||||
|
QVector<QString> result;
|
||||||
|
foreach(const QJsonValue& value, arr)
|
||||||
|
{
|
||||||
|
result << value.toString();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Backend::Utils::hashString(QString str)
|
||||||
|
{
|
||||||
|
return "0x" + QString::fromUtf8(QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Keccak_256).toHex());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backend::Utils::throwOnError(QJsonObject response) {
|
||||||
|
if(!response["error"].isUndefined() && !response["error"].toString().isEmpty()){
|
||||||
|
qWarning() << "RpcException: " << response["error"].toString();
|
||||||
|
throw Backend::RpcException(response["error"].toString().toStdString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include "constants.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
// TODO: merge with constants from backend/
|
||||||
|
|
||||||
|
|
||||||
|
QString Constants::applicationPath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Constants::tmpPath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Constants::cachePath(QString path)
|
||||||
|
{
|
||||||
|
return QFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + path).absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Constants::ensureDirectories()
|
||||||
|
{
|
||||||
|
if(Constants::applicationPath().isEmpty())
|
||||||
|
{
|
||||||
|
QDir d{Constants::applicationPath()};
|
||||||
|
if(!d.mkpath(d.absolutePath()))
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
|
msgBox.setText("Cannot determine storage location");
|
||||||
|
msgBox.exec();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Constants
|
||||||
|
{
|
||||||
|
const QString DataDir = "/data";
|
||||||
|
const QString Keystore = "/data/keystore";
|
||||||
|
|
||||||
|
QString applicationPath(QString path = "");
|
||||||
|
QString tmpPath(QString path = "");
|
||||||
|
QString cachePath(QString path = "");
|
||||||
|
bool ensureDirectories();
|
||||||
|
|
||||||
|
} // namespace Constants
|
|
@ -0,0 +1,30 @@
|
||||||
|
if(APPLE)
|
||||||
|
file(GLOB_RECURSE SOURCES *.cpp *.mm)
|
||||||
|
else()
|
||||||
|
file(GLOB_RECURSE SOURCES *.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(DOtherSide
|
||||||
|
${SOURCES})
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
target_include_directories(DOtherSide
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../bottles/hunspell/include)
|
||||||
|
else()
|
||||||
|
target_include_directories(DOtherSide
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(DOtherSide
|
||||||
|
PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
Qt${QT_VERSION_MAJOR}::Gui
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
# Add here any vendor folder
|
||||||
|
#../../vendor/vendor_name_goes_here/
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "DOtherSide.h"
|
||||||
|
#include "SpellChecker.h"
|
||||||
|
#include "StatusSyntaxHighlighter.h"
|
||||||
|
#include "StatusWindow.h"
|
||||||
|
|
||||||
|
void DOtherSide::registerMetaTypes()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<QVector<int>>();
|
||||||
|
qmlRegisterType<StatusWindow>("DotherSide", 0, 1, "StatusWindow");
|
||||||
|
qmlRegisterType<StatusSyntaxHighlighterHelper>("DotherSide", 0, 1, "StatusSyntaxHighlighter");
|
||||||
|
qmlRegisterType<SpellChecker>("DotherSide", 0, 1, "SpellChecker");
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class DOtherSide {
|
||||||
|
public:
|
||||||
|
static void registerMetaTypes();
|
||||||
|
};
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "DOtherSide/DOtherSideSingleInstance.h"
|
||||||
|
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int ReadWriteTimeoutMs = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleInstance::SingleInstance(const QString &uniqueName, const QString &eventStr, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_localServer(new QLocalServer(this))
|
||||||
|
{
|
||||||
|
QString socketName = uniqueName;
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
socketName = QString("/tmp/%1").arg(socketName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QLocalSocket localSocket;
|
||||||
|
localSocket.connectToServer(socketName);
|
||||||
|
|
||||||
|
// the first instance start will be delayed by this timeout (ms) to ensure there are no other instances.
|
||||||
|
// note: this is an ad-hoc timeout value selected based on prior experience.
|
||||||
|
if (!localSocket.waitForConnected(100)) {
|
||||||
|
connect(m_localServer, &QLocalServer::newConnection, this, &SingleInstance::handleNewConnection);
|
||||||
|
// on *nix a crashed process will leave /tmp/xyz file preventing to start a new server.
|
||||||
|
// therefore, if we were unable to connect, then we assume the server died and we need to clean up.
|
||||||
|
// p.s. on Windows, this function does nothing.
|
||||||
|
QLocalServer::removeServer(socketName);
|
||||||
|
if (!m_localServer->listen(socketName)) {
|
||||||
|
qWarning() << "QLocalServer::listen(" << socketName << ") failed";
|
||||||
|
}
|
||||||
|
} else if (!eventStr.isEmpty()) {
|
||||||
|
localSocket.write(eventStr.toUtf8() + '\n');
|
||||||
|
localSocket.waitForBytesWritten(ReadWriteTimeoutMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleInstance::~SingleInstance()
|
||||||
|
{
|
||||||
|
if (m_localServer->isListening()) {
|
||||||
|
m_localServer->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SingleInstance::isFirstInstance() const
|
||||||
|
{
|
||||||
|
return m_localServer->isListening();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleInstance::handleNewConnection()
|
||||||
|
{
|
||||||
|
emit secondInstanceDetected();
|
||||||
|
|
||||||
|
auto socket = m_localServer->nextPendingConnection();
|
||||||
|
if (socket->waitForReadyRead(ReadWriteTimeoutMs) && socket->canReadLine()) {
|
||||||
|
auto event = socket->readLine();
|
||||||
|
emit eventReceived(QString::fromUtf8(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
socket->deleteLater();
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef SINGLEINSTANCE_H
|
||||||
|
#define SINGLEINSTANCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLocalServer;
|
||||||
|
|
||||||
|
class SingleInstance : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// uniqueName - the name of named pipe
|
||||||
|
// eventStr - optional event to send if another instance is detected
|
||||||
|
explicit SingleInstance(const QString &uniqueName, const QString &eventStr, QObject *parent = nullptr);
|
||||||
|
~SingleInstance() override;
|
||||||
|
|
||||||
|
bool isFirstInstance() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void secondInstanceDetected();
|
||||||
|
void eventReceived(const QString &eventStr);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleNewConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLocalServer *m_localServer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SINGLEINSTANCE_H
|
|
@ -0,0 +1,185 @@
|
||||||
|
#include "SpellChecker.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#include "hunspell/hunspell.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLocale>
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <QInputMethod>
|
||||||
|
|
||||||
|
SpellChecker::SpellChecker(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
, m_hunspell(nullptr)
|
||||||
|
#endif
|
||||||
|
, m_userDict("userDict_")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SpellChecker::~SpellChecker()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
delete m_hunspell;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpellChecker::spell(const QString &word)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
return m_hunspell->spell(m_codec->fromUnicode(word).toStdString());
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpellChecker::isInit() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
return !m_hunspell;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellChecker::initHunspell()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (m_hunspell) {
|
||||||
|
delete m_hunspell;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString dictFile = QGuiApplication::applicationDirPath() + "/dictionaries/" + m_lang + "/index.dic";
|
||||||
|
QString affixFile = QGuiApplication::applicationDirPath() + "/dictionaries/" + m_lang + "/index.aff";
|
||||||
|
QByteArray dictFilePathBA = dictFile.toLocal8Bit();
|
||||||
|
QByteArray affixFilePathBA = affixFile.toLocal8Bit();
|
||||||
|
m_hunspell = new Hunspell(affixFilePathBA.constData(),
|
||||||
|
dictFilePathBA.constData());
|
||||||
|
|
||||||
|
// detect encoding analyzing the SET option in the affix file
|
||||||
|
auto encoding = QStringLiteral("ISO8859-15");
|
||||||
|
QFile _affixFile(affixFile);
|
||||||
|
if (_affixFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QTextStream stream(&_affixFile);
|
||||||
|
QRegularExpression enc_detector(
|
||||||
|
QStringLiteral("^\\s*SET\\s+([A-Z0-9\\-]+)\\s*"),
|
||||||
|
QRegularExpression::CaseInsensitiveOption);
|
||||||
|
QString sLine;
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
sLine = stream.readLine();
|
||||||
|
if (sLine.isEmpty()) { continue; }
|
||||||
|
match = enc_detector.match(sLine);
|
||||||
|
if (match.hasMatch()) {
|
||||||
|
encoding = match.captured(1);
|
||||||
|
qDebug() << "Encoding set to " + encoding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_affixFile.close();
|
||||||
|
}
|
||||||
|
m_codec = QTextCodec::codecForName(encoding.toLatin1().constData());
|
||||||
|
|
||||||
|
QString userDict = m_userDict + m_lang + ".txt";
|
||||||
|
|
||||||
|
if (!userDict.isEmpty()) {
|
||||||
|
QFile userDictonaryFile(userDict);
|
||||||
|
if (userDictonaryFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QTextStream stream(&userDictonaryFile);
|
||||||
|
for (QString word = stream.readLine();
|
||||||
|
!word.isEmpty();
|
||||||
|
word = stream.readLine())
|
||||||
|
ignoreWord(word);
|
||||||
|
userDictonaryFile.close();
|
||||||
|
} else {
|
||||||
|
qWarning() << "User dictionary in " << userDict
|
||||||
|
<< "could not be opened";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "User dictionary not set.";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList SpellChecker::suggest(const QString &word)
|
||||||
|
{
|
||||||
|
int numSuggestions = 0;
|
||||||
|
QVariantList suggestions;
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
std::vector<std::string> wordlist;
|
||||||
|
wordlist = m_hunspell->suggest(m_codec->fromUnicode(word).toStdString());
|
||||||
|
|
||||||
|
numSuggestions = static_cast<int>(wordlist.size());
|
||||||
|
if (numSuggestions > 0) {
|
||||||
|
suggestions.reserve(numSuggestions);
|
||||||
|
for (int i = 0; i < numSuggestions; i++) {
|
||||||
|
suggestions << m_codec->toUnicode(
|
||||||
|
QByteArray::fromStdString(wordlist[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellChecker::ignoreWord(const QString &word)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
m_hunspell->add(m_codec->fromUnicode(word).constData());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellChecker::addToUserWordlist(const QString &word)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
QString userDict = m_userDict + m_lang + ".txt";
|
||||||
|
if (!userDict.isEmpty()) {
|
||||||
|
QFile userDictonaryFile(userDict);
|
||||||
|
if (userDictonaryFile.open(QIODevice::Append)) {
|
||||||
|
QTextStream stream(&userDictonaryFile);
|
||||||
|
stream << word << "\n";
|
||||||
|
userDictonaryFile.close();
|
||||||
|
} else {
|
||||||
|
qWarning() << "User dictionary in " << userDict
|
||||||
|
<< "could not be opened for appending a new word";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "User dictionary not set.";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& SpellChecker::lang() const
|
||||||
|
{
|
||||||
|
return m_lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellChecker::setLang(const QString& lang)
|
||||||
|
{
|
||||||
|
if (m_lang != lang) {
|
||||||
|
m_lang = lang;
|
||||||
|
initHunspell();
|
||||||
|
emit langChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& SpellChecker::userDict() const
|
||||||
|
{
|
||||||
|
return m_userDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellChecker::setUserDict(const QString& userDict)
|
||||||
|
{
|
||||||
|
if (m_userDict != userDict) {
|
||||||
|
m_userDict = userDict;
|
||||||
|
emit userDictChanged();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QQuickTextDocument>
|
||||||
|
#include <QSyntaxHighlighter>
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
class Hunspell;
|
||||||
|
#endif
|
||||||
|
class QTextCodec;
|
||||||
|
|
||||||
|
class SpellChecker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString lang READ lang WRITE setLang NOTIFY langChanged)
|
||||||
|
Q_PROPERTY(QString userDict READ userDict WRITE setUserDict NOTIFY userDictChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SpellChecker(QObject *parent = nullptr);
|
||||||
|
~SpellChecker();
|
||||||
|
|
||||||
|
Q_INVOKABLE bool spell(const QString& word);
|
||||||
|
Q_INVOKABLE QVariantList suggest(const QString &word);
|
||||||
|
Q_INVOKABLE void ignoreWord(const QString &word);
|
||||||
|
Q_INVOKABLE void addToUserWordlist(const QString &word);
|
||||||
|
Q_INVOKABLE bool isInit() const;
|
||||||
|
|
||||||
|
const QString& lang() const;
|
||||||
|
void setLang(const QString& lang);
|
||||||
|
|
||||||
|
const QString& userDict() const;
|
||||||
|
void setUserDict(const QString& userDict);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void langChanged();
|
||||||
|
void userDictChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initHunspell();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_lang;
|
||||||
|
QString m_userDict;
|
||||||
|
|
||||||
|
QQuickTextDocument *m_document;
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
Hunspell *m_hunspell;
|
||||||
|
#endif
|
||||||
|
QTextCodec *m_codec;
|
||||||
|
};
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "StatusSyntaxHighlighter.h"
|
||||||
|
#include <QQuickTextDocument>
|
||||||
|
|
||||||
|
StatusSyntaxHighlighter::StatusSyntaxHighlighter(QTextDocument *parent)
|
||||||
|
: QSyntaxHighlighter(parent)
|
||||||
|
{
|
||||||
|
HighlightingRule rule;
|
||||||
|
|
||||||
|
//BOLD
|
||||||
|
singlelineBoldFormat.setFontWeight(QFont::Bold);
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\*\\*(.*?)\\*\\*"));
|
||||||
|
rule.format = singlelineBoldFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//BOLD
|
||||||
|
|
||||||
|
//ITALIC
|
||||||
|
singleLineItalicFormat.setFontItalic(true);
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\*(.*?)\\*"));
|
||||||
|
rule.format = singleLineItalicFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//ITALIC
|
||||||
|
|
||||||
|
//CODE
|
||||||
|
singlelineCodeBlockFormat.setFontFamily("Roboto Mono");
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\`(.*?)\\`"));
|
||||||
|
rule.format = singlelineCodeBlockFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//CODE
|
||||||
|
|
||||||
|
//STRIKETHROUGH
|
||||||
|
singleLineStrikeThroughFormat.setFontStrikeOut(true);
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\~+(.*?)\\~+"));
|
||||||
|
rule.format = singleLineStrikeThroughFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//STRIKETHROUGH
|
||||||
|
|
||||||
|
//CODE BLOCK
|
||||||
|
multiLineCodeBlockFormat.setFontFamily("Roboto Mono");
|
||||||
|
rule.pattern = QRegularExpression(QStringLiteral("\\`\\`\\`(.*?)\\`\\`\\`"));
|
||||||
|
rule.format = multiLineCodeBlockFormat;
|
||||||
|
highlightingRules.append(rule);
|
||||||
|
//CODE BLOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusSyntaxHighlighter::highlightBlock(const QString &text)
|
||||||
|
{
|
||||||
|
for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
|
||||||
|
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
|
||||||
|
while (matchIterator.hasNext()) {
|
||||||
|
QRegularExpressionMatch match = matchIterator.next();
|
||||||
|
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCurrentBlockState(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickTextDocument *StatusSyntaxHighlighterHelper::quickTextDocument() const {
|
||||||
|
return m_quicktextdocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusSyntaxHighlighterHelper::setQuickTextDocument(
|
||||||
|
QQuickTextDocument *quickTextDocument) {
|
||||||
|
m_quicktextdocument = quickTextDocument;
|
||||||
|
if (m_quicktextdocument) {
|
||||||
|
new StatusSyntaxHighlighter(m_quicktextdocument->textDocument());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSyntaxHighlighter>
|
||||||
|
#include <QTextCharFormat>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
class QQuickTextDocument;
|
||||||
|
|
||||||
|
class StatusSyntaxHighlighter : public QSyntaxHighlighter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
StatusSyntaxHighlighter(QTextDocument *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void highlightBlock(const QString &text) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct HighlightingRule
|
||||||
|
{
|
||||||
|
QRegularExpression pattern;
|
||||||
|
QTextCharFormat format;
|
||||||
|
};
|
||||||
|
QVector<HighlightingRule> highlightingRules;
|
||||||
|
|
||||||
|
QTextCharFormat singlelineBoldFormat;
|
||||||
|
QTextCharFormat singleLineItalicFormat;
|
||||||
|
QTextCharFormat singlelineCodeBlockFormat;
|
||||||
|
QTextCharFormat singleLineStrikeThroughFormat;
|
||||||
|
QTextCharFormat multiLineCodeBlockFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StatusSyntaxHighlighterHelper : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QQuickTextDocument *quickTextDocument READ quickTextDocument WRITE
|
||||||
|
setQuickTextDocument NOTIFY quickTextDocumentChanged)
|
||||||
|
public:
|
||||||
|
StatusSyntaxHighlighterHelper(QObject *parent = nullptr)
|
||||||
|
: QObject(parent), m_quicktextdocument(nullptr) {}
|
||||||
|
QQuickTextDocument *quickTextDocument() const;
|
||||||
|
void setQuickTextDocument(QQuickTextDocument *quickTextDocument);
|
||||||
|
signals:
|
||||||
|
void quickTextDocumentChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QQuickTextDocument *m_quicktextdocument;
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "StatusWindow.h"
|
||||||
|
|
||||||
|
StatusWindow::StatusWindow(QWindow *parent)
|
||||||
|
: QQuickWindow(parent),
|
||||||
|
m_isFullScreen(false)
|
||||||
|
{
|
||||||
|
removeTitleBar();
|
||||||
|
|
||||||
|
connect(this, &QQuickWindow::windowStateChanged, [&](Qt::WindowState windowState) {
|
||||||
|
if (windowState == Qt::WindowNoState) {
|
||||||
|
removeTitleBar();
|
||||||
|
m_isFullScreen = false;
|
||||||
|
emit isFullScreenChanged();
|
||||||
|
} else if (windowState == Qt::WindowFullScreen) {
|
||||||
|
m_isFullScreen = true;
|
||||||
|
emit isFullScreenChanged();
|
||||||
|
showTitleBar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusWindow::toggleFullScreen()
|
||||||
|
{
|
||||||
|
if (m_isFullScreen) {
|
||||||
|
showNormal();
|
||||||
|
} else {
|
||||||
|
showFullScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StatusWindow::isFullScreen() const
|
||||||
|
{
|
||||||
|
return m_isFullScreen;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QQuickWindow>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
class StatusWindow: public QQuickWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(bool isFullScreen READ isFullScreen NOTIFY isFullScreenChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit StatusWindow(QWindow *parent = nullptr);
|
||||||
|
|
||||||
|
Q_INVOKABLE void toggleFullScreen();
|
||||||
|
|
||||||
|
bool isFullScreen() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void updatePosition() {
|
||||||
|
auto point = QPoint(screen()->geometry().center().x() - geometry().width() / 2, screen()->geometry().center().y() - geometry().height() / 2);
|
||||||
|
if (point != this->position()) {
|
||||||
|
this->setPosition(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void isFullScreenChanged();
|
||||||
|
void secondInstanceDetected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void removeTitleBar();
|
||||||
|
void showTitleBar();
|
||||||
|
void initCallbacks();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isFullScreen;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "StatusWindow.h"
|
||||||
|
|
||||||
|
#include <Foundation/Foundation.h>
|
||||||
|
#include <AppKit/NSView.h>
|
||||||
|
#include <AppKit/NSWindow.h>
|
||||||
|
#include <AppKit/NSColor.h>
|
||||||
|
#include <AppKit/NSToolbar.h>
|
||||||
|
#include <AppKit/NSButton.h>
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
void StatusWindow::removeTitleBar()
|
||||||
|
{
|
||||||
|
NSView *nsView = reinterpret_cast<NSView*>(this->winId());
|
||||||
|
NSWindow *window = [nsView window];
|
||||||
|
|
||||||
|
window.titlebarAppearsTransparent = true;
|
||||||
|
window.titleVisibility = NSWindowTitleHidden;
|
||||||
|
window.styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||||
|
NSButton* close = [window standardWindowButton:NSWindowCloseButton];
|
||||||
|
NSView* titleBarContainerView = close.superview.superview;
|
||||||
|
[titleBarContainerView setHidden:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusWindow::showTitleBar()
|
||||||
|
{
|
||||||
|
NSView *nsView = reinterpret_cast<NSView*>(this->winId());
|
||||||
|
NSWindow *window = [nsView window];
|
||||||
|
|
||||||
|
window.titlebarAppearsTransparent = true;
|
||||||
|
window.titleVisibility = NSWindowTitleHidden;
|
||||||
|
window.styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||||
|
NSButton* close = [window standardWindowButton:NSWindowCloseButton];
|
||||||
|
NSView* titleBarContainerView = close.superview.superview;
|
||||||
|
[titleBarContainerView setHidden:NO];
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue