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
|
|
@ -31,4 +31,57 @@ status-react-translations/
|
|||
/.update.timestamp
|
||||
notarization.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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 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