From 40528a84b7c713e309781077dfd4f427a4a77bd9 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 18:05:56 +0100 Subject: [PATCH 001/979] scripted-diff: Rename UNIQUE_NAME to BITCOIN_UNIQUE_NAME The `nb30.h` Windows header defines `UNIQUE_NAME` as a macro. This introduces a fragile dependency on header inclusion order: if Windows headers happen to be included before using `UNIQUE_NAME`, the preprocessor expands it into a numeric literal, causing syntax errors. Rename the macro to `BITCOIN_UNIQUE_NAME` to remove this fragility and avoid the collision entirely. -BEGIN VERIFY SCRIPT- sed -i 's/\/BITCOIN_UNIQUE_NAME/g' $(git grep -l 'UNIQUE_NAME' ./src/) -END VERIFY SCRIPT- --- src/logging/timer.h | 8 ++++---- src/sync.h | 4 ++-- src/test/util/logging.h | 2 +- src/util/macros.h | 2 +- src/util/stdmutex.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/logging/timer.h b/src/logging/timer.h index 2b183822e9..1706c9e71b 100644 --- a/src/logging/timer.h +++ b/src/logging/timer.h @@ -99,13 +99,13 @@ class Timer #define LOG_TIME_MICROS_WITH_CATEGORY(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) #define LOG_TIME_MILLIS_WITH_CATEGORY(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) #define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category, /* msg_on_completion=*/false) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category, /* msg_on_completion=*/false) #define LOG_TIME_SECONDS(end_msg) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg) #endif // BITCOIN_LOGGING_TIMER_H diff --git a/src/sync.h b/src/sync.h index 123184d44f..28bc78e911 100644 --- a/src/sync.h +++ b/src/sync.h @@ -251,7 +251,7 @@ class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock // it is not possible to use the lock's copy of the mutex for that purpose. // Instead, the original mutex needs to be passed back to the reverse_lock for // the sake of thread-safety analysis, but it is not actually used otherwise. -#define REVERSE_LOCK(g, cs) typename std::decay::type::reverse_lock UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__) +#define REVERSE_LOCK(g, cs) typename std::decay::type::reverse_lock BITCOIN_UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__) // When locking a Mutex, require negative capability to ensure the lock // is not already held @@ -265,7 +265,7 @@ inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNE template inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; } -#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) +#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) \ UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \ UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__) diff --git a/src/test/util/logging.h b/src/test/util/logging.h index ed3ee19e1b..6df208d841 100644 --- a/src/test/util/logging.h +++ b/src/test/util/logging.h @@ -39,6 +39,6 @@ class DebugLogHelper MatchFn m_match; }; -#define ASSERT_DEBUG_LOG(message) DebugLogHelper UNIQUE_NAME(debugloghelper)(message) +#define ASSERT_DEBUG_LOG(message) DebugLogHelper BITCOIN_UNIQUE_NAME(debugloghelper)(message) #endif // BITCOIN_TEST_UTIL_LOGGING_H diff --git a/src/util/macros.h b/src/util/macros.h index 9ad2fa6ef4..eedd23c692 100644 --- a/src/util/macros.h +++ b/src/util/macros.h @@ -8,7 +8,7 @@ #define PASTE(x, y) x ## y #define PASTE2(x, y) PASTE(x, y) -#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) +#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__) /** * Converts the parameter X to a string after macro replacement on X has been performed. diff --git a/src/util/stdmutex.h b/src/util/stdmutex.h index ab89a98768..d2ac1ba195 100644 --- a/src/util/stdmutex.h +++ b/src/util/stdmutex.h @@ -38,6 +38,6 @@ class LOCKABLE StdMutex : public std::mutex }; // Provide STDLOCK(..) wrapper around StdMutex::Guard that checks the lock is not already held -#define STDLOCK(cs) StdMutex::Guard UNIQUE_NAME(criticalblock){StdMutex::CheckNotHeld(cs)} +#define STDLOCK(cs) StdMutex::Guard BITCOIN_UNIQUE_NAME(criticalblock){StdMutex::CheckNotHeld(cs)} #endif // BITCOIN_UTIL_STDMUTEX_H From 960d7f7f27ae0e6bb7e09912c666afaeb285f2a4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 10:38:16 +0100 Subject: [PATCH 002/979] cmake: Require Qt Qml and Qt Quick modules when `BUILD_GUI=ON` --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69ee54611a..2c86b4acbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,7 +254,7 @@ if(WITH_USDT) endif() if(BUILD_GUI) - set(qt_components Core Gui Widgets LinguistTools) + set(qt_components Core Gui Widgets Qml Quick QuickControls2 LinguistTools) if(ENABLE_WALLET) list(APPEND qt_components Network) endif() From 5c114faafcae53522750d39f3d89d2e9b1b8a2a5 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:33:21 +0100 Subject: [PATCH 003/979] depends: Add Qt Qml and Qt Quick modules --- depends/packages/native_qt.mk | 22 +++++++++++++++--- depends/packages/qt.mk | 27 +++++++++++++++++++++- depends/packages/qt_details.mk | 6 +++++ depends/patches/qt/qtbase_skip_tools.patch | 8 +++---- depends/patches/qt/static_fixes.patch | 10 ++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) diff --git a/depends/packages/native_qt.mk b/depends/packages/native_qt.mk index 2bf088c10a..6d2aec3734 100644 --- a/depends/packages/native_qt.mk +++ b/depends/packages/native_qt.mk @@ -11,13 +11,21 @@ $(package)_patches += rcc_hardcode_timestamp.patch $(package)_patches += qttools_skip_dependencies.patch $(package)_patches += fix-macos26-qyield.patch +$(package)_qtshadertools_file_name=$(qt_details_qtshadertools_file_name) +$(package)_qtshadertools_sha256_hash=$(qt_details_qtshadertools_sha256_hash) + +$(package)_qtdeclarative_file_name=$(qt_details_qtdeclarative_file_name) +$(package)_qtdeclarative_sha256_hash=$(qt_details_qtdeclarative_sha256_hash) + $(package)_qttranslations_file_name=$(qt_details_qttranslations_file_name) $(package)_qttranslations_sha256_hash=$(qt_details_qttranslations_sha256_hash) $(package)_qttools_file_name=$(qt_details_qttools_file_name) $(package)_qttools_sha256_hash=$(qt_details_qttools_sha256_hash) -$(package)_extra_sources := $($(package)_qttranslations_file_name) +$(package)_extra_sources := $($(package)_qtshadertools_file_name) +$(package)_extra_sources += $($(package)_qtdeclarative_file_name) +$(package)_extra_sources += $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) $(package)_top_download_path=$(qt_details_top_download_path) @@ -51,14 +59,13 @@ $(package)_config_opts += -no-feature-concurrent $(package)_config_opts += -no-feature-network $(package)_config_opts += -no-feature-printsupport $(package)_config_opts += -no-feature-sql -$(package)_config_opts += -no-feature-testlib $(package)_config_opts += -no-feature-xml -$(package)_config_opts += -no-gui $(package)_config_opts += -no-widgets $(package)_config_opts += -no-glib $(package)_config_opts += -no-icu $(package)_config_opts += -no-libudev +$(package)_config_opts += -no-opengl $(package)_config_opts += -no-openssl $(package)_config_opts += -no-zstd $(package)_config_opts += -qt-pcre @@ -67,6 +74,7 @@ $(package)_config_opts += -no-feature-backtrace $(package)_config_opts += -no-feature-permissions $(package)_config_opts += -no-feature-process $(package)_config_opts += -no-feature-settings +$(package)_config_opts += -no-feature-vulkan # Core tools. $(package)_config_opts += -no-feature-androiddeployqt @@ -106,6 +114,8 @@ endef define $(package)_fetch_cmds $(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \ +$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qtshadertools_file_name),$($(package)_qtshadertools_file_name),$($(package)_qtshadertools_sha256_hash)) && \ +$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qtdeclarative_file_name),$($(package)_qtdeclarative_file_name),$($(package)_qtdeclarative_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttranslations_file_name),$($(package)_qttranslations_file_name),$($(package)_qttranslations_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttools_file_name),$($(package)_qttools_file_name),$($(package)_qttools_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_top_download_path),$($(package)_top_cmakelists_download_file),$($(package)_top_cmakelists_file_name)-$($(package)_version),$($(package)_top_cmakelists_sha256_hash)) && \ @@ -116,6 +126,8 @@ endef define $(package)_extract_cmds mkdir -p $($(package)_extract_dir) && \ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtshadertools_sha256_hash) $($(package)_source_dir)/$($(package)_qtshadertools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtdeclarative_sha256_hash) $($(package)_source_dir)/$($(package)_qtdeclarative_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_top_cmakelists_sha256_hash) $($(package)_source_dir)/$($(package)_top_cmakelists_file_name)-$($(package)_version)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ @@ -124,6 +136,10 @@ define $(package)_extract_cmds $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p qtbase && \ $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \ + mkdir -p qtshadertools && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtshadertools_file_name) -C qtshadertools && \ + mkdir -p qtdeclarative && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtdeclarative_file_name) -C qtdeclarative && \ mkdir -p qttranslations && \ $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \ mkdir -p qttools && \ diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 9b7cec341d..b0f51fe437 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -27,13 +27,21 @@ $(package)_patches += fix-gcc16-sfinae-qanystringview.patch $(package)_patches += fix-macos26-qyield.patch $(package)_patches += fix-qbytearray-include.patch +$(package)_qtshadertools_file_name=$(qt_details_qtshadertools_file_name) +$(package)_qtshadertools_sha256_hash=$(qt_details_qtshadertools_sha256_hash) + +$(package)_qtdeclarative_file_name=$(qt_details_qtdeclarative_file_name) +$(package)_qtdeclarative_sha256_hash=$(qt_details_qtdeclarative_sha256_hash) + $(package)_qttranslations_file_name=$(qt_details_qttranslations_file_name) $(package)_qttranslations_sha256_hash=$(qt_details_qttranslations_sha256_hash) $(package)_qttools_file_name=$(qt_details_qttools_file_name) $(package)_qttools_sha256_hash=$(qt_details_qttools_sha256_hash) -$(package)_extra_sources := $($(package)_qttranslations_file_name) +$(package)_extra_sources := $($(package)_qtshadertools_file_name) +$(package)_extra_sources += $($(package)_qtdeclarative_file_name) +$(package)_extra_sources += $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) $(package)_top_download_path=$(qt_details_top_download_path) @@ -127,6 +135,9 @@ $(package)_config_opts += -no-feature-macdeployqt $(package)_config_opts += -no-feature-qmake $(package)_config_opts += -no-feature-windeployqt +# QML features. +$(package)_config_opts += -no-feature-qml-profiler + ifeq ($(host),$(build)) # Qt Tools module. $(package)_config_opts += -feature-linguist @@ -224,6 +235,8 @@ endef define $(package)_fetch_cmds $(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \ +$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qtshadertools_file_name),$($(package)_qtshadertools_file_name),$($(package)_qtshadertools_sha256_hash)) && \ +$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qtdeclarative_file_name),$($(package)_qtdeclarative_file_name),$($(package)_qtdeclarative_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttranslations_file_name),$($(package)_qttranslations_file_name),$($(package)_qttranslations_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttools_file_name),$($(package)_qttools_file_name),$($(package)_qttools_sha256_hash)) && \ $(call fetch_file,$(package),$($(package)_top_download_path),$($(package)_top_cmakelists_download_file),$($(package)_top_cmakelists_file_name)-$($(package)_version),$($(package)_top_cmakelists_sha256_hash)) && \ @@ -235,6 +248,8 @@ ifeq ($(host),$(build)) define $(package)_extract_cmds mkdir -p $($(package)_extract_dir) && \ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtshadertools_sha256_hash) $($(package)_source_dir)/$($(package)_qtshadertools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtdeclarative_sha256_hash) $($(package)_source_dir)/$($(package)_qtdeclarative_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_top_cmakelists_sha256_hash) $($(package)_source_dir)/$($(package)_top_cmakelists_file_name)-$($(package)_version)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ @@ -243,6 +258,10 @@ define $(package)_extract_cmds $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p qtbase && \ $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \ + mkdir -p qtshadertools && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtshadertools_file_name) -C qtshadertools && \ + mkdir -p qtdeclarative && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtdeclarative_file_name) -C qtdeclarative && \ mkdir -p qttranslations && \ $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \ mkdir -p qttools && \ @@ -256,12 +275,18 @@ else define $(package)_extract_cmds mkdir -p $($(package)_extract_dir) && \ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtshadertools_sha256_hash) $($(package)_source_dir)/$($(package)_qtshadertools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_qtdeclarative_sha256_hash) $($(package)_source_dir)/$($(package)_qtdeclarative_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_top_cmakelists_sha256_hash) $($(package)_source_dir)/$($(package)_top_cmakelists_file_name)-$($(package)_version)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_top_cmake_ecmoptionaladdsubdirectory_sha256_hash) $($(package)_source_dir)/$($(package)_top_cmake_ecmoptionaladdsubdirectory_file_name)-$($(package)_version)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ echo "$($(package)_top_cmake_qttoplevelhelpers_sha256_hash) $($(package)_source_dir)/$($(package)_top_cmake_qttoplevelhelpers_file_name)-$($(package)_version)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p qtbase && \ $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \ + mkdir -p qtshadertools && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtshadertools_file_name) -C qtshadertools && \ + mkdir qtdeclarative && \ + $(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtdeclarative_file_name) -C qtdeclarative && \ cp $($(package)_source_dir)/$($(package)_top_cmakelists_file_name)-$($(package)_version) ./$($(package)_top_cmakelists_file_name) && \ mkdir -p cmake && \ cp $($(package)_source_dir)/$($(package)_top_cmake_ecmoptionaladdsubdirectory_file_name)-$($(package)_version) cmake/$($(package)_top_cmake_ecmoptionaladdsubdirectory_file_name) && \ diff --git a/depends/packages/qt_details.mk b/depends/packages/qt_details.mk index e49ac6a287..1e7264ab1a 100644 --- a/depends/packages/qt_details.mk +++ b/depends/packages/qt_details.mk @@ -5,6 +5,12 @@ qt_details_suffix := everywhere-src-$(qt_details_version).tar.xz qt_details_qtbase_file_name := qtbase-$(qt_details_suffix) qt_details_qtbase_sha256_hash := 56001b905601bb9023d399f3ba780d7fa940f3e4861e496a7c490331f49e0b80 +qt_details_qtshadertools_file_name = qtshadertools-$(qt_details_suffix) +qt_details_qtshadertools_sha256_hash = f6ec88bf42deba84d8f6b5d0914636ceed4749ccb51d1945b2f79b322b7ecf47 + +qt_details_qtdeclarative_file_name = qtdeclarative-$(qt_details_suffix) +qt_details_qtdeclarative_sha256_hash = 1f03a2b8f5588b4face7da87926e9b2c1372b3a32157c52df07a75067a9db1af + qt_details_qttranslations_file_name := qttranslations-$(qt_details_suffix) qt_details_qttranslations_sha256_hash := c3c61d79c3d8fe316a20b3617c64673ce5b5519b2e45535f49bee313152fa531 diff --git a/depends/patches/qt/qtbase_skip_tools.patch b/depends/patches/qt/qtbase_skip_tools.patch index eef65425d4..d5377c3f45 100644 --- a/depends/patches/qt/qtbase_skip_tools.patch +++ b/depends/patches/qt/qtbase_skip_tools.patch @@ -3,8 +3,7 @@ Skip building/installing unneeded tools: 1. Wrapper CMake scripts. 2. CI support files. 3. tracepointgen and tracegen tools. -4. Qt Look Ahead LR Parser Generator (qlalr). -5. Qt Vulkan Header Generator (qvkgen). +4. Qt Vulkan Header Generator (qvkgen). --- a/qtbase/cmake/QtBaseGlobalTargets.cmake @@ -47,11 +46,10 @@ Skip building/installing unneeded tools: --- a/qtbase/src/tools/CMakeLists.txt +++ b/qtbase/src/tools/CMakeLists.txt -@@ -11,8 +11,6 @@ if (QT_FEATURE_dbus) - add_subdirectory(qdbuscpp2xml) +@@ -12,7 +12,6 @@ if (QT_FEATURE_dbus) add_subdirectory(qdbusxml2cpp) endif() --add_subdirectory(qlalr) + add_subdirectory(qlalr) -add_subdirectory(qvkgen) if (QT_FEATURE_commandlineparser) add_subdirectory(qtpaths) diff --git a/depends/patches/qt/static_fixes.patch b/depends/patches/qt/static_fixes.patch index 1ae3f5774a..317dd3608d 100644 --- a/depends/patches/qt/static_fixes.patch +++ b/depends/patches/qt/static_fixes.patch @@ -78,3 +78,13 @@ index e8fb442dd43..e964138115c 100644 CODE "// xkb.h is using a variable called 'explicit', which is a reserved keyword in C++ #define explicit dont_use_cxx_explicit +--- a/qtbase/src/plugins/platforms/xcb/CMakeLists.txt ++++ b/qtbase/src/plugins/platforms/xcb/CMakeLists.txt +@@ -65,6 +65,7 @@ qt_internal_add_module(XcbQpaPrivate + XCB::XFIXES + XCB::XKB + XKB::XKB ++ $ + NO_UNITY_BUILD # X11 define clashes + ) + From 1668daab1606e345b45a8d2d75e066b468be7e87 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:19:00 +0100 Subject: [PATCH 004/979] cmake: Add `bitcoin-qml` executable Github-Pull: bitcoin-core/gui-qml#5 Rebased-From: cc7f2542a4a2e0bd80e1ca0ff25151280860d0cf --- src/qml/CMakeLists.txt | 57 ++++++++++++++++++++++++++++++++++++++++ src/qml/bitcoin.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++ src/qml/bitcoin.h | 10 +++++++ src/qml/main.cpp | 25 ++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 src/qml/CMakeLists.txt create mode 100644 src/qml/bitcoin.cpp create mode 100644 src/qml/bitcoin.h create mode 100644 src/qml/main.cpp diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt new file mode 100644 index 0000000000..727ca78a32 --- /dev/null +++ b/src/qml/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (c) 2025-present The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit/. + +set(CMAKE_AUTOMOC ON) + +add_library(bitcoinqml STATIC + bitcoin.cpp +) + +target_compile_definitions(bitcoinqml + PUBLIC + QT_NO_KEYWORDS + QT_USE_QSTRINGBUILDER +) + +target_include_directories(bitcoinqml + PUBLIC + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_BINARY_DIR}/src +) + +target_link_libraries(bitcoinqml + PUBLIC + core_interface + bitcoin_node + Qt6::Qml + Qt6::Widgets + Qt6::Quick +) + +add_executable(bitcoin-qml WIN32 + main.cpp + ${PROJECT_SOURCE_DIR}/src/init/bitcoin-qt.cpp +) + +# TODO: Switch to own resource file. +add_windows_resources(bitcoin-qml ${PROJECT_SOURCE_DIR}/src/qt/res/bitcoin-qt-res.rc) +add_windows_application_manifest(bitcoin-qml) + +target_link_libraries(bitcoin-qml + PRIVATE + bitcoinqml + bitcoinqt +) + +install_binary_component(bitcoin-qml) + +# Use the `bitcoin-qml` target as a drop-in replacement +# for the legacy QtWidgets-based `bitcoin-qt`. +set_target_properties(bitcoin-qt PROPERTIES + OUTPUT_NAME "bitcoin-qt-legacy" + EXCLUDE_FROM_ALL TRUE +) +set_target_properties(bitcoin-qml PROPERTIES + OUTPUT_NAME "bitcoin-qt" +) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp new file mode 100644 index 0000000000..c941e72c41 --- /dev/null +++ b/src/qml/bitcoin.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2021-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/license/mit/. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace { +void SetupUIArgs(ArgsManager& argsman) +{ + argsman.AddArg("-lang=", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); + argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); + argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); + argsman.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); +} +} // namespace + + +int QmlGuiMain(int argc, char* argv[]) +{ + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + + SetupEnvironment(); + util::ThreadSetInternalName("main"); + + // Subscribe to global signals from core + btcsignals::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox); + btcsignals::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion); + btcsignals::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage); + + QGuiApplication app(argc, argv); + + // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + SetupServerArgs(gArgs); + SetupUIArgs(gArgs); + std::string error; + if (!gArgs.ParseParameters(argc, argv, error)) { + InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error))); + return EXIT_FAILURE; + } + + return app.exec(); +} diff --git a/src/qml/bitcoin.h b/src/qml/bitcoin.h new file mode 100644 index 0000000000..9fa0043b54 --- /dev/null +++ b/src/qml/bitcoin.h @@ -0,0 +1,10 @@ +// Copyright (c) 2021-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/license/mit/. + +#ifndef BITCOIN_QML_BITCOIN_H +#define BITCOIN_QML_BITCOIN_H + +int QmlGuiMain(int argc, char* argv[]); + +#endif // BITCOIN_QML_BITCOIN_H diff --git a/src/qml/main.cpp b/src/qml/main.cpp new file mode 100644 index 0000000000..ed502a9f1b --- /dev/null +++ b/src/qml/main.cpp @@ -0,0 +1,25 @@ +// Copyright (c) 2018-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +#include + +#include +#include + +/** Translate string to current locale using Qt. */ +extern const TranslateFn G_TRANSLATION_FUN = [](const char* psz) { + return QCoreApplication::translate("bitcoin-core", psz).toStdString(); +}; + +const std::function G_TEST_GET_FULL_NAME{}; + +MAIN_FUNCTION +{ + return QmlGuiMain(argc, argv); +} From 12b5c026982648e76f4601f64b8f8b5d0343a3b8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:44:31 +0100 Subject: [PATCH 005/979] cmake: Incorporate `qml` subdirectory --- cmake/module/Maintenance.cmake | 6 +++--- contrib/guix/symbol-check.py | 2 ++ src/CMakeLists.txt | 1 + src/qt/CMakeLists.txt | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmake/module/Maintenance.cmake b/cmake/module/Maintenance.cmake index 15fbf2bea8..20d2ff0f09 100644 --- a/cmake/module/Maintenance.cmake +++ b/cmake/module/Maintenance.cmake @@ -36,7 +36,7 @@ function(add_windows_deploy_target) OUTPUT ${PROJECT_BINARY_DIR}/bitcoin-win64-setup.exe COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/release COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ - COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ + COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ COMMAND ${CMAKE_STRIP} $ -o ${PROJECT_BINARY_DIR}/release/$ @@ -65,8 +65,8 @@ function(add_macos_deploy_target) add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/${macos_app}/Contents/MacOS/Bitcoin-Qt - COMMAND ${CMAKE_COMMAND} --install ${PROJECT_BINARY_DIR} --config $ --component bitcoin-qt --prefix ${macos_app}/Contents/MacOS --strip - COMMAND ${CMAKE_COMMAND} -E rename ${macos_app}/Contents/MacOS/bin/$ ${macos_app}/Contents/MacOS/Bitcoin-Qt + COMMAND ${CMAKE_COMMAND} --install ${PROJECT_BINARY_DIR} --config $ --component bitcoin-qml --prefix ${macos_app}/Contents/MacOS --strip + COMMAND ${CMAKE_COMMAND} -E rename ${macos_app}/Contents/MacOS/bin/$ ${macos_app}/Contents/MacOS/Bitcoin-Qt COMMAND ${CMAKE_COMMAND} -E rm -rf ${macos_app}/Contents/MacOS/bin COMMAND ${CMAKE_COMMAND} -E rm -rf ${macos_app}/Contents/MacOS/share VERBATIM diff --git a/contrib/guix/symbol-check.py b/contrib/guix/symbol-check.py index 86b7965277..65f3f5f599 100755 --- a/contrib/guix/symbol-check.py +++ b/contrib/guix/symbol-check.py @@ -130,6 +130,7 @@ 'Metal', # 3D graphics 'QuartzCore', # animation 'Security', # access control and authentication +'SystemConfiguration', # network configuration 'UniformTypeIdentifiers', # collection of types that map to MIME and file types } @@ -158,6 +159,7 @@ 'NETAPI32.dll', # network management 'ole32.dll', # component object model 'OLEAUT32.dll', # OLE Automation API +'Secur32.dll', # SSPI (Security Support Provider Interface) 'SHLWAPI.dll', # light weight shell API 'USER32.dll', # user interface 'USERENV.dll', # user management diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 524c28165c..be9dd7069a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -398,6 +398,7 @@ endif() if(BUILD_GUI) add_subdirectory(qt) + add_subdirectory(qml) endif() diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 58fa08b56a..12b9e37d19 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -270,7 +270,7 @@ target_link_libraries(bitcoin-qt ) import_plugins(bitcoin-qt) -install_binary_component(bitcoin-qt HAS_MANPAGE) +# install_binary_component(bitcoin-qt HAS_MANPAGE) if(WIN32) set_target_properties(bitcoin-qt PROPERTIES WIN32_EXECUTABLE TRUE) endif() From 642d4de621918a100fdb0dc12e9f226782dbefbd Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:42:19 +0300 Subject: [PATCH 006/979] qml: Add bitcoin module Rebased-From: cc7f2542a4a2e0bd80e1ca0ff25151280860d0cf Github-Pull: bitcoin-core/gui-qml#5 --- src/qml/bitcoin.cpp | 30 ++++++++++++++---------------- src/qml/bitcoin.h | 4 ++-- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c941e72c41..a815ad155a 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -1,25 +1,23 @@ -// Copyright (c) 2021-present The Bitcoin Core developers +// Copyright (c) 2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or https://opensource.org/license/mit/. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include -#include -#include #include #include -#include -#include #include +#include #include #include +#include #include -#include +#include #include #include +#include namespace { void SetupUIArgs(ArgsManager& argsman) @@ -34,24 +32,24 @@ void SetupUIArgs(ArgsManager& argsman) int QmlGuiMain(int argc, char* argv[]) { - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); - - SetupEnvironment(); - util::ThreadSetInternalName("main"); + NodeContext node_context; + std::unique_ptr node = interfaces::MakeNode(&node_context); // Subscribe to global signals from core - btcsignals::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox); - btcsignals::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion); - btcsignals::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage); + boost::signals2::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox); + boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion); + boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage); + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error))); + InitError(strprintf(Untranslated("Error parsing command line arguments: %s\n"), error)); return EXIT_FAILURE; } diff --git a/src/qml/bitcoin.h b/src/qml/bitcoin.h index 9fa0043b54..77e7102e6d 100644 --- a/src/qml/bitcoin.h +++ b/src/qml/bitcoin.h @@ -1,6 +1,6 @@ -// Copyright (c) 2021-present The Bitcoin Core developers +// Copyright (c) 2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or https://opensource.org/license/mit/. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_QML_BITCOIN_H #define BITCOIN_QML_BITCOIN_H From 9351b62d4fbd01d957732ad74571e9c6afe392cc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 4 Jul 2021 16:56:27 +0300 Subject: [PATCH 007/979] qml: Add stub window Rebased-From: e2104f89096c74eacbd2e5626e7bf4a5bc63f6c0 Github-Pull: bitcoin-core/gui-qml#5 --- src/qml/bitcoin.cpp | 8 ++++++++ src/qml/bitcoin_qml.qrc | 5 +++++ src/qml/pages/stub.qml | 9 +++++++++ 3 files changed, 22 insertions(+) create mode 100644 src/qml/bitcoin_qml.qrc create mode 100644 src/qml/pages/stub.qml diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index a815ad155a..099073a103 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include namespace { void SetupUIArgs(ArgsManager& argsman) @@ -40,9 +42,15 @@ int QmlGuiMain(int argc, char* argv[]) boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion); boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage); + Q_INIT_RESOURCE(bitcoin_qml); + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); + if (engine.rootObjects().isEmpty()) { + return EXIT_FAILURE; + } // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. SetupServerArgs(gArgs); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc new file mode 100644 index 0000000000..66ad312f8f --- /dev/null +++ b/src/qml/bitcoin_qml.qrc @@ -0,0 +1,5 @@ + + + pages/stub.qml + + diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml new file mode 100644 index 0000000000..b535b249cc --- /dev/null +++ b/src/qml/pages/stub.qml @@ -0,0 +1,9 @@ +import QtQuick.Controls 2.12 + +ApplicationWindow { + id: appWindow + title: "Bitcoin Core TnG" + minimumWidth: 750 + minimumHeight: 450 + visible: true +} From 190adc498d81b3565649cbd24018d8d602a50d8b Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Fri, 9 Jul 2021 03:27:23 -0400 Subject: [PATCH 008/979] doc: introduce qml/README.md This introduces a README.md for the qml directory. It outlines the goals and limitations of the projects and stages for future development and build notes. Rebased-From: 605842aef74c8c9f79e1fa631b496a991a78a30f Github-Pull: bitcoin-core/gui-qml#14 --- src/qml/README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/qml/README.md diff --git a/src/qml/README.md b/src/qml/README.md new file mode 100644 index 0000000000..f56a633d9b --- /dev/null +++ b/src/qml/README.md @@ -0,0 +1,55 @@ +# Bitcoin Core QML GUI + +**WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** + +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +# Goals and Limitations + +The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. +This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. + +The primary goals of the project can be summed up as follows: + +- Implement UX/UI best-practices as documented in the [Bitcoin Design Guide](https://bitcoin.design/guide/) +- Engage with the Bitcoin Design community to implement well-designed features +- Work alongside the Bitcoin Design community to develop an aesthetic GUI +- Develop a mobile-optimized GUI + +It is important that we stay as conflict-free as possible with the Bitcoin Core repo. +As such, this project will aim to make very few changes outside of the qml directory. +Pull requests must be focused on developing the GUI itself, adding build support, +or improving relevant documentation. + +Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. + +# Development Process + +This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. + +Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). + +# Compile and Run + +The master branch is only guaranteed to work and build on Debian-based systems and macOS. +Support for more systems will be confirmed and documented as the project matures. + +### Dependencies +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies: + +``` +sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev +``` + +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. + +### Build + +For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. + +To add support for building the qml GUI, +you must configure with the following option: + +``` +./configure --with-qml +``` From db8ded08bf57892c914c9776f077e5944d9aaeb9 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 13 Jul 2021 19:10:58 +0300 Subject: [PATCH 009/979] qml: Add NodeModel module Rebased-From: 9bc8a6d090f1748a7d95ba4ae419181ff45d6168 Github-Pull: bitcoin-core/gui-qml#11 --- src/qml/.gitignore | 1 + src/qml/README.md | 55 ------------------------------------------- src/qml/bitcoin.cpp | 7 ++++++ src/qml/nodemodel.cpp | 5 ++++ src/qml/nodemodel.h | 17 +++++++++++++ 5 files changed, 30 insertions(+), 55 deletions(-) create mode 100644 src/qml/.gitignore delete mode 100644 src/qml/README.md create mode 100644 src/qml/nodemodel.cpp create mode 100644 src/qml/nodemodel.h diff --git a/src/qml/.gitignore b/src/qml/.gitignore new file mode 100644 index 0000000000..17eb6eecef --- /dev/null +++ b/src/qml/.gitignore @@ -0,0 +1 @@ +/moc_*.cpp diff --git a/src/qml/README.md b/src/qml/README.md deleted file mode 100644 index f56a633d9b..0000000000 --- a/src/qml/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Bitcoin Core QML GUI - -**WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** - -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - -# Goals and Limitations - -The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. -This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. - -The primary goals of the project can be summed up as follows: - -- Implement UX/UI best-practices as documented in the [Bitcoin Design Guide](https://bitcoin.design/guide/) -- Engage with the Bitcoin Design community to implement well-designed features -- Work alongside the Bitcoin Design community to develop an aesthetic GUI -- Develop a mobile-optimized GUI - -It is important that we stay as conflict-free as possible with the Bitcoin Core repo. -As such, this project will aim to make very few changes outside of the qml directory. -Pull requests must be focused on developing the GUI itself, adding build support, -or improving relevant documentation. - -Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. - -# Development Process - -This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. - -Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). - -# Compile and Run - -The master branch is only guaranteed to work and build on Debian-based systems and macOS. -Support for more systems will be confirmed and documented as the project matures. - -### Dependencies -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies: - -``` -sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev -``` - -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. - -### Build - -For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. - -To add support for building the qml GUI, -you must configure with the following option: - -``` -./configure --with-qml -``` diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 099073a103..d85998d851 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include #include #include @@ -46,7 +48,12 @@ int QmlGuiMain(int argc, char* argv[]) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); + + NodeModel node_model; + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("nodeModel", &node_model); + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); if (engine.rootObjects().isEmpty()) { return EXIT_FAILURE; diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp new file mode 100644 index 0000000000..5093b41cc1 --- /dev/null +++ b/src/qml/nodemodel.cpp @@ -0,0 +1,5 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h new file mode 100644 index 0000000000..f291db5e6d --- /dev/null +++ b/src/qml/nodemodel.h @@ -0,0 +1,17 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QML_NODEMODEL_H +#define BITCOIN_QML_NODEMODEL_H + +#include + +/** Model for Bitcoin network client. */ +class NodeModel : public QObject +{ + Q_OBJECT + +}; + +#endif // BITCOIN_QML_NODEMODEL_H From 512b0c74faa328395297b962a680c110296eb004 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 13 Jul 2021 20:45:38 +0300 Subject: [PATCH 010/979] qml: Add start/shutdown functionality Rebased-From: 3ad6d11f9bdae7c7dd18091161e7ae5f8237e41a Github-Pull: bitcoin-core/gui-qml#11 --- src/qml/bitcoin.cpp | 58 +++++++++++++++++++++++++++++------------- src/qml/nodemodel.cpp | 12 +++++++++ src/qml/nodemodel.h | 7 +++++ src/qml/pages/stub.qml | 3 +++ 4 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index d85998d851..302a35e393 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -36,20 +37,50 @@ void SetupUIArgs(ArgsManager& argsman) int QmlGuiMain(int argc, char* argv[]) { - NodeContext node_context; - std::unique_ptr node = interfaces::MakeNode(&node_context); - - // Subscribe to global signals from core - boost::signals2::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox); - boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion); - boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage); - Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); + // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + SetupServerArgs(gArgs); + SetupUIArgs(gArgs); + std::string error; + if (!gArgs.ParseParameters(argc, argv, error)) { + InitError(strprintf(Untranslated("Error parsing command line arguments: %s\n"), error)); + return EXIT_FAILURE; + } + + CheckDataDirOption(); + + gArgs.ReadConfigFiles(error, true); + + SelectParams(gArgs.GetChainName()); + + // Default printtoconsole to false for the GUI. GUI programs should not + // print to the console unnecessarily. + gArgs.SoftSetBoolArg("-printtoconsole", false); + InitLogging(gArgs); + InitParameterInteraction(gArgs); + + NodeContext node_context; + node_context.args = &gArgs; + std::unique_ptr node = interfaces::MakeNode(&node_context); + node->baseInitialize(); + NodeModel node_model; + InitExecutor init_executor{*node}; + QObject::connect(&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize); + QObject::connect(&node_model, &NodeModel::requestedShutdown, &init_executor, &InitExecutor::shutdown); + // QObject::connect(&init_executor, &InitExecutor::initializeResult, &node_model, &NodeModel::initializeResult); + QObject::connect(&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection); + // QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException); + + qGuiApp->setQuitOnLastWindowClosed(false); + QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] { + node->startShutdown(); + node_model.startNodeShutdown(); + }); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("nodeModel", &node_model); @@ -59,14 +90,5 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - SetupServerArgs(gArgs); - SetupUIArgs(gArgs); - std::string error; - if (!gArgs.ParseParameters(argc, argv, error)) { - InitError(strprintf(Untranslated("Error parsing command line arguments: %s\n"), error)); - return EXIT_FAILURE; - } - - return app.exec(); + return qGuiApp->exec(); } diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 5093b41cc1..2111900503 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -3,3 +3,15 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include + +#include + +void NodeModel::startNodeInitializionThread() +{ + Q_EMIT requestedInitialize(); +} + +void NodeModel::startNodeShutdown() +{ + Q_EMIT requestedShutdown(); +} diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index f291db5e6d..9daed8e51a 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -12,6 +12,13 @@ class NodeModel : public QObject { Q_OBJECT +public: + Q_INVOKABLE void startNodeInitializionThread(); + void startNodeShutdown(); + +Q_SIGNALS: + void requestedInitialize(); + void requestedShutdown(); }; #endif // BITCOIN_QML_NODEMODEL_H diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index b535b249cc..1e7fd17413 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -1,3 +1,4 @@ +import QtQml 2.12 import QtQuick.Controls 2.12 ApplicationWindow { @@ -6,4 +7,6 @@ ApplicationWindow { minimumWidth: 750 minimumHeight: 450 visible: true + + Component.onCompleted: nodeModel.startNodeInitializionThread(); } From a73fcd10a8dbea83ea4bd8de6f711a82f760bd92 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 28 Jul 2021 14:25:22 -0400 Subject: [PATCH 011/979] doc: document minimum required qt version The minimum required qt version is defined as the version specified by our build system. This will minimize divergence from upstream and avoid costly changes. Rebased-From: d899656500fdbde5d79e913faf49298bfbab337a Github-Pull: bitcoin-core/gui-qml#16 --- src/qml/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/README.md b/src/qml/README.md index f56a633d9b..2c488a6b0e 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -29,6 +29,12 @@ This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitc Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). +## Minimum Required Qt Version + +All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.12.11](https://github.com/bitcoin-core/gui-qml/blob/a79a2249d027047f08dffe3f04951d52eac198f1/depends/packages/qt.mk#L2). + +As the Qt Version changes upstream, refactoring is allowed to use the now available features. + # Compile and Run The master branch is only guaranteed to work and build on Debian-based systems and macOS. From 5071083ab5bfcc027e3f494a20e79fdd3cb7bca3 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 7 Aug 2021 21:05:31 +0300 Subject: [PATCH 012/979] qml: Add message box for InitError calls Rebased-From: 5e848d589560bf6c4caa1bf1e614a41f103bc1ff Github-Pull: bitcoin-core/gui-qml#17 --- src/qml/bitcoin.cpp | 16 ++++++++++++++++ src/qml/bitcoin_qml.qrc | 1 + src/qml/pages/initerrormessage.qml | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/qml/pages/initerrormessage.qml diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 302a35e393..00f49cd289 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -32,6 +32,18 @@ void SetupUIArgs(ArgsManager& argsman) argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); argsman.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); } + +bool InitErrorMessageBox( + const bilingual_str& message, + [[maybe_unused]] const std::string& caption, + [[maybe_unused]] unsigned int style) +{ + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty("message", QString::fromStdString(message.translated)); + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/initerrormessage.qml"))); + qGuiApp->exec(); + return false; +} } // namespace @@ -42,6 +54,8 @@ int QmlGuiMain(int argc, char* argv[]) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); + auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); + // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. SetupServerArgs(gArgs); SetupUIArgs(gArgs); @@ -68,6 +82,8 @@ int QmlGuiMain(int argc, char* argv[]) std::unique_ptr node = interfaces::MakeNode(&node_context); node->baseInitialize(); + handler_message_box.disconnect(); + NodeModel node_model; InitExecutor init_executor{*node}; QObject::connect(&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 66ad312f8f..172301459e 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -1,5 +1,6 @@ + pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml new file mode 100644 index 0000000000..f6437299ea --- /dev/null +++ b/src/qml/pages/initerrormessage.qml @@ -0,0 +1,11 @@ +import QtQuick 2.12 +import QtQuick.Dialogs 1.3 + +MessageDialog { + id: messageDialog + title: "Bitcoin Core TnG" + icon: StandardIcon.Critical + text: message + onAccepted: Qt.quit() + Component.onCompleted: visible = true +} From c25b9968b3fe69a7bcbe333f58bf075cd2d8cd10 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 7 Aug 2021 21:26:55 +0300 Subject: [PATCH 013/979] qml: Handle initialization errors Rebased-From: a3b9d538cd1759f5a639fd4e3a0a1c620e33d04d Github-Pull: bitcoin-core/gui-qml#17 --- src/qml/bitcoin.cpp | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 00f49cd289..c2eeba72b7 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -56,20 +56,43 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - // Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + NodeContext node_context; + + /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - InitError(strprintf(Untranslated("Error parsing command line arguments: %s\n"), error)); + InitError(strprintf(Untranslated("Cannot parse command line arguments: %s\n"), error)); + return EXIT_FAILURE; + } + + /// Determine availability of data directory. + if (!CheckDataDirOption()) { + InitError(strprintf(Untranslated("Specified data directory \"%s\" does not exist.\n"), gArgs.GetArg("-datadir", ""))); return EXIT_FAILURE; } - CheckDataDirOption(); + /// Read and parse bitcoin.conf file. + if (!gArgs.ReadConfigFiles(error, true)) { + InitError(strprintf(Untranslated("Cannot parse configuration file: %s\n"), error)); + return EXIT_FAILURE; + } - gArgs.ReadConfigFiles(error, true); + /// Check for chain settings (Params() calls are only valid after this clause). + try { + SelectParams(gArgs.GetChainName()); + } catch(std::exception &e) { + InitError(Untranslated(strprintf("%s\n", e.what()))); + return EXIT_FAILURE; + } - SelectParams(gArgs.GetChainName()); + /// Read and parse settings.json file. + if (!gArgs.InitSettings(error)) { + InitError(Untranslated(error)); + return EXIT_FAILURE; + } // Default printtoconsole to false for the GUI. GUI programs should not // print to the console unnecessarily. @@ -77,10 +100,11 @@ int QmlGuiMain(int argc, char* argv[]) InitLogging(gArgs); InitParameterInteraction(gArgs); - NodeContext node_context; - node_context.args = &gArgs; std::unique_ptr node = interfaces::MakeNode(&node_context); - node->baseInitialize(); + if (!node->baseInitialize()) { + // A dialog with detailed error will have been shown by InitError(). + return EXIT_FAILURE; + } handler_message_box.disconnect(); From fef49c781f4ee86515a44fae4e881c320c812de2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 13:26:46 +0300 Subject: [PATCH 014/979] qml: Check whether initerrormessage.qml is loaded correctly Rebased-From: 15b7c5ad971fc36f20bf0651967811e98749b9dc Github-Pull: bitcoin-core/gui-qml#22 --- src/qml/bitcoin.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c4ad71439b..911fdfbc9e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -24,16 +24,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); -Q_IMPORT_PLUGIN(QtQuick2Plugin); -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -Q_IMPORT_PLUGIN(QtQuickControls1Plugin); -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { @@ -51,6 +41,9 @@ bool InitErrorMessageBox( QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("message", QString::fromStdString(message.translated)); engine.load(QUrl(QStringLiteral("qrc:///qml/pages/initerrormessage.qml"))); + if (engine.rootObjects().isEmpty()) { + return EXIT_FAILURE; + } qGuiApp->exec(); return false; } From 9e23aacdbdd8689d1dff4b82ee267f3ab4cdbc55 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:50:48 +0300 Subject: [PATCH 015/979] build, qml: Add qtdeclarative module Rebased-From: e61d42de6f1725761dbb82e189c99ae34a89f898 Github-Pull: bitcoin-core/gui-qml#19 --- src/qml/bitcoin.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c2eeba72b7..c9329e3124 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -24,6 +24,12 @@ #include #include +#if defined(QT_STATICPLUGIN) +#include +Q_IMPORT_PLUGIN(QtQuick2Plugin); +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +#endif + namespace { void SetupUIArgs(ArgsManager& argsman) { From 014cfa510f44b1fda1885ed045d47d7eb697fdf3 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:52:01 +0300 Subject: [PATCH 016/979] build, qml: Add qtquickcontrols module Rebased-From: 3ddb9b3213e5465a3fab608a10117afba8186060 Github-Pull: bitcoin-core/gui-qml#19 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c9329e3124..4f89843062 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -26,8 +26,10 @@ #if defined(QT_STATICPLUGIN) #include +Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +Q_IMPORT_PLUGIN(QtQuickControls1Plugin); #endif namespace { From a08e55b91750e400483fb16af38519416e333b1c Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:54:11 +0300 Subject: [PATCH 017/979] build, qml: Add qtquickcontrols2 module Rebased-From: 8793ae7bbf2ed474a55abd22635ff3c747e2f475 Github-Pull: bitcoin-core/gui-qml#19 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4f89843062..c4ad71439b 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -30,6 +30,8 @@ Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls1Plugin); +Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From a1d03fd50e28115f2fc0a14a4bb98aae997e76ec Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 23 Aug 2021 02:13:10 -0400 Subject: [PATCH 018/979] doc: document runtime dependencies This documents the runtime dependencies required for proper execution. These runtime dependencies were introduced in PR17. Rebased-From: 28b17929522444eaaf0d3d6675a07cf6c363914c Github-Pull: bitcoin-core/gui-qml#21 --- src/qml/README.md | 9 ++++++++- src/qml/bitcoin.cpp | 13 ------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 2c488a6b0e..3166f65009 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -41,12 +41,19 @@ The master branch is only guaranteed to work and build on Debian-based systems a Support for more systems will be confirmed and documented as the project matures. ### Dependencies -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies: +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev ``` +The following runtime dependencies are also required for dynamic builds; +they are not needed for static builds: + +``` +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +``` + No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. ### Build diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9de999c613..c2eeba72b7 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -24,16 +24,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); -Q_IMPORT_PLUGIN(QtQuick2Plugin); -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -Q_IMPORT_PLUGIN(QtQuickControls1Plugin); -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { @@ -51,9 +41,6 @@ bool InitErrorMessageBox( QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("message", QString::fromStdString(message.translated)); engine.load(QUrl(QStringLiteral("qrc:///qml/pages/initerrormessage.qml"))); - if (engine.rootObjects().isEmpty()) { - return EXIT_FAILURE; - } qGuiApp->exec(); return false; } From 903a0bed7d49e7847893998efaa7f44d84dd7904 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 28 Aug 2021 01:27:41 +0300 Subject: [PATCH 019/979] qml: Add GUIUtil::LogQtInfo() call Rebased-From: 6be715b837093a1fbd880dc33e838d5a4dfd62f0 Github-Pull: bitcoin-core/gui-qml#24 --- src/qml/bitcoin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9de999c613..a4a32c8260 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,8 @@ int QmlGuiMain(int argc, char* argv[]) InitLogging(gArgs); InitParameterInteraction(gArgs); + GUIUtil::LogQtInfo(); + std::unique_ptr node = interfaces::MakeNode(&node_context); if (!node->baseInitialize()) { // A dialog with detailed error will have been shown by InitError(). From 283ec4eacdbf9ea31bf4e2abb89bb5605ae01147 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 31 Aug 2021 00:36:59 +0300 Subject: [PATCH 020/979] scripted-diff: Add copyright headers to QML files -BEGIN VERIFY SCRIPT- git ls-files ./src/qml/pages | xargs -I % ./contrib/devtools/copyright_header.py insert % -END VERIFY SCRIPT- Rebased-From: f82209dc026452c1fa510c23762553cbae75de60 Github-Pull: bitcoin-core/gui-qml#34 --- src/qml/pages/initerrormessage.qml | 4 ++++ src/qml/pages/stub.qml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index f6437299ea..f305993dc3 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -1,3 +1,7 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + import QtQuick 2.12 import QtQuick.Dialogs 1.3 diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 1e7fd17413..2c651737a4 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -1,3 +1,7 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + import QtQml 2.12 import QtQuick.Controls 2.12 From ad110f12ae048758d4bfd647c6cff872167d2052 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 30 Aug 2021 14:22:46 +0300 Subject: [PATCH 021/979] qml: Add QmlUtil::GraphicsApi utility function Rebased-From: 5eb4b726d002ef847b5b4b592ed464fa54a91bfe Github-Pull: bitcoin-core/gui-qml#32 --- src/qml/util.cpp | 34 ++++++++++++++++++++++++++++++++++ src/qml/util.h | 27 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/qml/util.cpp create mode 100644 src/qml/util.h diff --git a/src/qml/util.cpp b/src/qml/util.cpp new file mode 100644 index 0000000000..800751d457 --- /dev/null +++ b/src/qml/util.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include +#include +#include + +namespace QmlUtil { + +QString GraphicsApi(QQuickWindow* window) +{ + switch (window->rendererInterface()->graphicsApi()) { + case QSGRendererInterface::Unknown: return "Unknown"; + case QSGRendererInterface::Software: return "The Qt Quick 2D Renderer"; + case QSGRendererInterface::OpenGL: return "OpenGL ES 2.0 or higher"; + case QSGRendererInterface::Direct3D12: return "Direct3D 12"; + case QSGRendererInterface::OpenVG: return "OpenVG via EGL"; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + case QSGRendererInterface::OpenGLRhi: return "OpenGL ES 2.0 or higher via a graphics abstraction layer"; + case QSGRendererInterface::Direct3D11Rhi: return "Direct3D 11 via a graphics abstraction layer"; + case QSGRendererInterface::VulkanRhi: return "Vulkan 1.0 via a graphics abstraction layer"; + case QSGRendererInterface::MetalRhi: return "Metal via a graphics abstraction layer"; + case QSGRendererInterface::NullRhi: return "Null (no output) via a graphics abstraction layer"; +#endif + } // no default case, so the compiler can warn about missing cases + assert(false); +} + +} // namespace QmlUtil diff --git a/src/qml/util.h b/src/qml/util.h new file mode 100644 index 0000000000..6df5d2c2b5 --- /dev/null +++ b/src/qml/util.h @@ -0,0 +1,27 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QML_UTIL_H +#define BITCOIN_QML_UTIL_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QQuickWindow; +QT_END_NAMESPACE + +/** + * Utility functions used by the QML-based Bitcoin Core GUI. + */ +namespace QmlUtil { +/** +* Returns a human-readable description of the graphics API +* that is in use by the Qt Quick scene graph renderer. +*/ +QString GraphicsApi(QQuickWindow* window); + +} // namespace QmlUtil + +#endif // BITCOIN_QML_UTIL_H From 085dee93ab9e000230b8c7f5067ccd8a5fc1590e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 30 Aug 2021 14:44:32 +0300 Subject: [PATCH 022/979] qml: Use QmlUtil::GraphicsApi utility function for logging Rebased-From: c763435882a7f834095edd00233d28eb6f4ca016 Github-Pull: bitcoin-core/gui-qml#32 --- src/qml/bitcoin.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index a4a32c8260..593e7bab59 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,9 +20,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -146,5 +149,12 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + auto window = qobject_cast(engine.rootObjects().first()); + if (!window) { + return EXIT_FAILURE; + } + + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); + return qGuiApp->exec(); } From 50bd7aff401dc991473964f3d8ddba1663da5e16 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 29 Aug 2021 08:25:52 +0300 Subject: [PATCH 023/979] qml: Add blockTipHeight property to NodeModel, and expose it to QML Rebased-From: b6280a9c022ae5ac0c5c093ab77d86fd5bbbc652 Github-Pull: bitcoin-core/gui-qml#31 --- src/qml/nodemodel.cpp | 8 +++++++- src/qml/nodemodel.h | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 2111900503..a8d9c47e68 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -4,7 +4,13 @@ #include -#include +void NodeModel::setBlockTipHeight(int new_height) +{ + if (new_height != m_block_tip_height) { + m_block_tip_height = new_height; + Q_EMIT blockTipHeightChanged(); + } +} void NodeModel::startNodeInitializionThread() { diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index 9daed8e51a..91555c4ef4 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -11,14 +11,23 @@ class NodeModel : public QObject { Q_OBJECT + Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) public: + int blockTipHeight() const { return m_block_tip_height; } + void setBlockTipHeight(int new_height); + Q_INVOKABLE void startNodeInitializionThread(); void startNodeShutdown(); Q_SIGNALS: + void blockTipHeightChanged(); void requestedInitialize(); void requestedShutdown(); + +private: + // Properties that are exposed to QML. + int m_block_tip_height{0}; }; #endif // BITCOIN_QML_NODEMODEL_H From 1be40d57bac32c175767bb8c64811e40f7c3a3c2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 29 Aug 2021 09:22:51 +0300 Subject: [PATCH 024/979] qml: Add BlockCounter QML component prototype Rebased-From: 1441d5be79f161e7864bf5493b5ed68c51731eec Github-Pull: bitcoin-core/gui-qml#31 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/components/BlockCounter.qml | 21 +++++++++++++++++++++ src/qml/pages/stub.qml | 11 ++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/qml/components/BlockCounter.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 172301459e..f6e1e4fa6e 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -1,5 +1,6 @@ + components/BlockCounter.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml new file mode 100644 index 0000000000..e23ba7b72d --- /dev/null +++ b/src/qml/components/BlockCounter.qml @@ -0,0 +1,21 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// The BlockCounter component. + +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +Label { + property int blockHeight: 0 + background: Rectangle { + color: "black" + } + color: "orange" + padding: 16 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: height / 3 + text: blockHeight +} diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 2c651737a4..ee30cb735f 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,8 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQml 2.12 +import QtQuick 2.12 import QtQuick.Controls 2.12 +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow @@ -13,4 +15,11 @@ ApplicationWindow { visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); + + BitcoinCoreComponents.BlockCounter { + id: blockCounter + anchors.centerIn: parent + height: parent.height / 3 + blockHeight: nodeModel.blockTipHeight + } } From 82ce1655d9403fa398b7eec55a185e6047a41515 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 29 Aug 2021 09:27:38 +0300 Subject: [PATCH 025/979] qml: Pass Node instance to the NodeModel constructor Rebased-From: 219088dcd6703141f2834e0d3b1e80f66fe034bd Github-Pull: bitcoin-core/gui-qml#31 --- src/qml/bitcoin.cpp | 2 +- src/qml/nodemodel.cpp | 7 +++++++ src/qml/nodemodel.h | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 593e7bab59..16964d6214 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -127,7 +127,7 @@ int QmlGuiMain(int argc, char* argv[]) handler_message_box.disconnect(); - NodeModel node_model; + NodeModel node_model{*node}; InitExecutor init_executor{*node}; QObject::connect(&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize); QObject::connect(&node_model, &NodeModel::requestedShutdown, &init_executor, &InitExecutor::shutdown); diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index a8d9c47e68..b85d33bf80 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -4,6 +4,13 @@ #include +#include + +NodeModel::NodeModel(interfaces::Node& node) + : m_node{node} +{ +} + void NodeModel::setBlockTipHeight(int new_height) { if (new_height != m_block_tip_height) { diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index 91555c4ef4..24ce1a971c 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -7,6 +7,10 @@ #include +namespace interfaces { +class Node; +} + /** Model for Bitcoin network client. */ class NodeModel : public QObject { @@ -14,6 +18,8 @@ class NodeModel : public QObject Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) public: + explicit NodeModel(interfaces::Node& node); + int blockTipHeight() const { return m_block_tip_height; } void setBlockTipHeight(int new_height); @@ -28,6 +34,8 @@ class NodeModel : public QObject private: // Properties that are exposed to QML. int m_block_tip_height{0}; + + interfaces::Node& m_node; }; #endif // BITCOIN_QML_NODEMODEL_H From fc092e4685312025dffb742c3b3b224afca245d5 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 29 Aug 2021 09:29:30 +0300 Subject: [PATCH 026/979] qml: Connect NodeModel to the NotifyBlockTip core signal Rebased-From: 3ead757f60434933a915b0c726e58b419ea8b8c4 Github-Pull: bitcoin-core/gui-qml#31 --- src/qml/bitcoin.cpp | 2 +- src/qml/nodemodel.cpp | 17 +++++++++++++++++ src/qml/nodemodel.h | 11 +++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 16964d6214..31bb85aa33 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -131,7 +131,7 @@ int QmlGuiMain(int argc, char* argv[]) InitExecutor init_executor{*node}; QObject::connect(&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize); QObject::connect(&node_model, &NodeModel::requestedShutdown, &init_executor, &InitExecutor::shutdown); - // QObject::connect(&init_executor, &InitExecutor::initializeResult, &node_model, &NodeModel::initializeResult); + QObject::connect(&init_executor, &InitExecutor::initializeResult, &node_model, &NodeModel::initializeResult); QObject::connect(&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection); // QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException); diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index b85d33bf80..4ed4612aeb 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -5,10 +5,12 @@ #include #include +#include NodeModel::NodeModel(interfaces::Node& node) : m_node{node} { + ConnectToBlockTipSignal(); } void NodeModel::setBlockTipHeight(int new_height) @@ -28,3 +30,18 @@ void NodeModel::startNodeShutdown() { Q_EMIT requestedShutdown(); } + +void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::BlockAndHeaderTipInfo tip_info) +{ + // TODO: Handle the `success` parameter, + setBlockTipHeight(tip_info.block_height); +} + +void NodeModel::ConnectToBlockTipSignal() +{ + assert(!m_handler_notify_block_tip); + m_handler_notify_block_tip = m_node.handleNotifyBlockTip( + [this](SynchronizationState state, interfaces::BlockTip tip, double verification_progress) { + setBlockTipHeight(tip.block_height); + }); +} diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index 24ce1a971c..b3190a0199 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -5,6 +5,11 @@ #ifndef BITCOIN_QML_NODEMODEL_H #define BITCOIN_QML_NODEMODEL_H +#include +#include + +#include + #include namespace interfaces { @@ -26,6 +31,9 @@ class NodeModel : public QObject Q_INVOKABLE void startNodeInitializionThread(); void startNodeShutdown(); +public Q_SLOTS: + void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info); + Q_SIGNALS: void blockTipHeightChanged(); void requestedInitialize(); @@ -36,6 +44,9 @@ class NodeModel : public QObject int m_block_tip_height{0}; interfaces::Node& m_node; + std::unique_ptr m_handler_notify_block_tip; + + void ConnectToBlockTipSignal(); }; #endif // BITCOIN_QML_NODEMODEL_H From 55878284a8544af17fbc94e937cbb69b43cd87d8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 29 Sep 2021 01:02:20 +0300 Subject: [PATCH 027/979] Revert 8efd330d54e75e4a5de36278299b5227e4e5bfdf This change allows to merge bitcoin/bitcoin#22219 without conflicts. Rebased-From: 498a318f86b05af91b1665ceae9dbca330224850 Github-Pull: bitcoin-core/gui-qml#41 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 31 ++++++++++--------------------- src/qml/pages/stub.qml | 1 - 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index a6a8dd5007..3166f65009 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -51,7 +51,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index ef388b51ae..0e0bb4e1f0 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -16,24 +15,21 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include -#include #include #include -QT_BEGIN_NAMESPACE -class QMessageLogContext; -QT_END_NAMESPACE - #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); @@ -41,7 +37,6 @@ Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif @@ -68,22 +63,19 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } - -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); - } -} } // namespace int QmlGuiMain(int argc, char* argv[]) { +#ifdef WIN32 + util::WinCmdLineArgs winArgs; + std::tie(argc, argv) = winArgs.get(); +#endif // WIN32 + + SetupEnvironment(); + util::ThreadSetInternalName("main"); + Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); @@ -172,9 +164,6 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); - qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 2cc87449a4..ee30cb735f 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,7 +4,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From ef6a52545db3103daf32126dea7880246e8ce0df Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:13:33 +0300 Subject: [PATCH 028/979] qml: Add qInstallMessageHandler Rebased-From: 6521cb8f118535bacc4d1d291a97c6d2109855d1 Github-Pull: bitcoin-core/gui-qml#44 --- src/qml/bitcoin.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 31bb85aa33..3ec7d9e3d5 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -25,9 +26,14 @@ #include #include #include +#include #include #include +QT_BEGIN_NAMESPACE +class QMessageLogContext; +QT_END_NAMESPACE + #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); @@ -61,6 +67,17 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } + +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } +} } // namespace @@ -154,6 +171,9 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + // Install qDebug() message handler to route to debug.log + qInstallMessageHandler(DebugMessageHandler); + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); From d272f2f62f41c7f724b5873317c7a10f42123987 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 3 Oct 2021 14:32:13 +0300 Subject: [PATCH 029/979] qml, build, doc: Allow import QtQuick.Layouts Rebased-From: 5ce77ad32fcf392654f441f786aeb3d34ca7c08e Github-Pull: bitcoin-core/gui-qml#45 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 + src/qml/pages/stub.qml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 3166f65009..a6a8dd5007 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -51,7 +51,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 3ec7d9e3d5..ef388b51ae 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,6 +41,7 @@ Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ee30cb735f..2cc87449a4 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,6 +4,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From aa227ab1ff1a070464c27bb1d0d4ebaf45e6df4e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 3 Oct 2021 18:36:50 +0300 Subject: [PATCH 030/979] qml: Implement #22219 changes in the qml/bitcoin.cpp Rebased-From: ef05ff514e7b3fbfbc8cac6b149b48fbe6581d6e Github-Pull: bitcoin-core/gui-qml#48 --- src/qml/bitcoin.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 001e0f2303..c511df3508 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -91,9 +92,6 @@ int QmlGuiMain(int argc, char* argv[]) std::tie(argc, argv) = winArgs.get(); #endif // WIN32 - SetupEnvironment(); - util::ThreadSetInternalName("main"); - Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); @@ -102,6 +100,11 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + + SetupEnvironment(); + util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. node_context.args = &gArgs; @@ -147,7 +150,7 @@ int QmlGuiMain(int argc, char* argv[]) GUIUtil::LogQtInfo(); - std::unique_ptr node = interfaces::MakeNode(&node_context); + std::unique_ptr node = init->makeNode(); if (!node->baseInitialize()) { // A dialog with detailed error will have been shown by InitError(). return EXIT_FAILURE; From ac389d55345977ae0a2871fbfe49348d381c1627 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 17:55:39 +0300 Subject: [PATCH 031/979] qml: Add imageprovider module Rebased-From: 5efe6dc98ca3fc9288f54dcf884317c884d72ec9 Github-Pull: bitcoin-core/gui-qml#42 --- src/qml/imageprovider.cpp | 31 +++++++++++++++++++++++++++++++ src/qml/imageprovider.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/qml/imageprovider.cpp create mode 100644 src/qml/imageprovider.h diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp new file mode 100644 index 0000000000..88c9cae72a --- /dev/null +++ b/src/qml/imageprovider.cpp @@ -0,0 +1,31 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include +#include +#include +#include +#include + +ImageProvider::ImageProvider(const NetworkStyle* network_style) + : QQuickImageProvider{QQuickImageProvider::Pixmap}, + m_network_style{network_style} {} + +QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requested_size) +{ + if (!size || !requested_size.isValid()) { + return {}; + } + + if (id == "app") { + *size = requested_size; + return m_network_style->getAppIcon().pixmap(requested_size); + } + + return {}; +} diff --git a/src/qml/imageprovider.h b/src/qml/imageprovider.h new file mode 100644 index 0000000000..ba602d7184 --- /dev/null +++ b/src/qml/imageprovider.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QML_IMAGEPROVIDER_H +#define BITCOIN_QML_IMAGEPROVIDER_H + +#include +#include + +class NetworkStyle; + +QT_BEGIN_NAMESPACE +class QSize; +class QString; +QT_END_NAMESPACE + +class ImageProvider : public QQuickImageProvider +{ +public: + explicit ImageProvider(const NetworkStyle* network_style); + + QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requested_size) override; + +private: + const NetworkStyle* m_network_style; +}; + +#endif // BITCOIN_QML_IMAGEPROVIDER_H From 86bed69043e6e7c40a44743cd47c911c022d0586 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 18:25:50 +0300 Subject: [PATCH 032/979] qml: Integrate ImageProvider into qml/bitcoin.cpp Rebased-From: a9d9fa754dcda664807ea21eea9ea1921fe67bde Github-Pull: bitcoin-core/gui-qml#42 --- src/qml/bitcoin.cpp | 8 ++++++++ src/qml/bitcoin_qml.qrc | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c511df3508..6678cdd848 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -11,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -173,6 +176,11 @@ int QmlGuiMain(int argc, char* argv[]) }); QQmlApplicationEngine engine; + + QScopedPointer network_style{NetworkStyle::instantiate(Params().NetworkIDString())}; + assert(!network_style.isNull()); + engine.addImageProvider(QStringLiteral("images"), new ImageProvider{network_style.data()}); + engine.rootContext()->setContextProperty("nodeModel", &node_model); engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index f6e1e4fa6e..d851c44076 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -4,4 +4,7 @@ pages/initerrormessage.qml pages/stub.qml + + ../qt/res/icons/bitcoin.png + From 166d745ceeb272df99fe0dd4c138c5a2e47829da Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 20:14:35 +0300 Subject: [PATCH 033/979] qml: Add a demo Image object Rebased-From: b7171c8301c46b6e90988526cf04ac120a5522d0 Github-Pull: bitcoin-core/gui-qml#42 --- src/qml/pages/stub.qml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 2cc87449a4..cdee0fd0ce 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,10 +13,21 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 + background: Rectangle { + color: "black" + } visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent From a849c3fd98574e0ad59f7a7eb26b9bc9a3980490 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:33:02 +0300 Subject: [PATCH 034/979] qml: Drop erroneous `#include ` To use the `QStringLiteral` macro, the `QString` header should be included, that is done already. Rebased-From: a13a8684030a3edde4983a55adf15683595760e1 Github-Pull: bitcoin-core/gui-qml#55 --- src/qml/bitcoin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 6678cdd848..e0a5a3646b 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE From 83b9da3eedb291be53703126b57717079bffdcf5 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 10 Oct 2021 23:41:33 +0300 Subject: [PATCH 035/979] qml: Include missed headers Rebased-From: 6fb3246326994a77b88a325915890d6c29984600 Github-Pull: bitcoin-core/gui-qml#57 --- src/qml/bitcoin.cpp | 1 + src/qml/nodemodel.cpp | 2 ++ src/qml/util.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index e0a5a3646b..44301228c2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 4ed4612aeb..45601791df 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -7,6 +7,8 @@ #include #include +#include + NodeModel::NodeModel(interfaces::Node& node) : m_node{node} { diff --git a/src/qml/util.cpp b/src/qml/util.cpp index 800751d457..4624150e8b 100644 --- a/src/qml/util.cpp +++ b/src/qml/util.cpp @@ -4,6 +4,7 @@ #include +#include #include #include From 1d405482f76f85bee1e6ea38071971579682f505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 6 Oct 2021 15:10:02 +0100 Subject: [PATCH 036/979] qml: Add regular and semibold typefaces of Inter font Rebased-From: b36cf202875828979bb9ac497b3c4c9863921f19 Github-Pull: bitcoin-core/gui-qml#49 --- src/qml/bitcoin.cpp | 3 +++ src/qml/bitcoin_qml.qrc | 4 ++++ src/qml/components/BlockCounter.qml | 2 ++ src/qml/res/fonts/Inter-Regular.otf | Bin 0 -> 258992 bytes src/qml/res/fonts/Inter-SemiBold.otf | Bin 0 -> 270760 bytes 5 files changed, 9 insertions(+) create mode 100644 src/qml/res/fonts/Inter-Regular.otf create mode 100644 src/qml/res/fonts/Inter-SemiBold.otf diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 44301228c2..425b8fb2cf 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -175,6 +175,9 @@ int QmlGuiMain(int argc, char* argv[]) node_model.startNodeShutdown(); }); + GUIUtil::LoadFont(":/fonts/inter/regular"); + GUIUtil::LoadFont(":/fonts/inter/semibold"); + QQmlApplicationEngine engine; QScopedPointer network_style{NetworkStyle::instantiate(Params().NetworkIDString())}; diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index d851c44076..0cfcef47ef 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -7,4 +7,8 @@ ../qt/res/icons/bitcoin.png + + res/fonts/Inter-Regular.otf + res/fonts/Inter-SemiBold.otf + diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index e23ba7b72d..69ce238775 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -16,6 +16,8 @@ Label { padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter + font.family: "Inter" + font.styleName: "Semi Bold" font.pixelSize: height / 3 text: blockHeight } diff --git a/src/qml/res/fonts/Inter-Regular.otf b/src/qml/res/fonts/Inter-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..84e6a61c3c0f11fc8c88c9e7a8f6ed7f7bbc43b3 GIT binary patch literal 258992 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

-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 J>wTt%eg>tMGE@Kn literal 0 HcmV?d00001 diff --git a/src/qml/res/fonts/Inter-SemiBold.otf b/src/qml/res/fonts/Inter-SemiBold.otf new file mode 100644 index 0000000000000000000000000000000000000000..daf4c4413f7b682ee421fbde5097c7963e2fcdc4 GIT binary patch literal 270760 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�)R7q*RfL1#IqVC8%FR@DjH#uJX6-ep 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 Date: Thu, 21 Oct 2021 23:20:03 +0100 Subject: [PATCH 037/979] qml: Set tab focus behavior Rebased-From: 500a6d20be4a5993c7c33bc613f841eca2233642 Github-Pull: bitcoin-core/gui-qml#65 --- src/qml/bitcoin.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4b02e2ea86..54c7ccf4f8 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -97,16 +99,20 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 7cff9ecadd6810db1a5ff8fb409a2fac84eb6367 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 27 Oct 2021 14:49:32 -0400 Subject: [PATCH 038/979] multiprocess: add new bitcoin-qt init implementation to qml-gui This incorporates the new bitcoin-qt init implementation into the qml-gui. Rebased-From: 749470f8922b4ee47ed9e4b183648e5d22921c50 Github-Pull: bitcoin-core/gui-qml#72 --- src/qml/bitcoin.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 425b8fb2cf..4b02e2ea86 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -102,15 +101,12 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From e2190897f8e4d04421faa6161116bafaf8c6c876 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 11:44:00 +0300 Subject: [PATCH 039/979] doc: Add links to CI artifacts into README.md Rebased-From: bd7be7b76e5174b36007fdd3f6f36d5a37edcbcb Github-Pull: bitcoin-core/gui-qml#76 --- src/qml/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/README.md b/src/qml/README.md index a6a8dd5007..22b0b90074 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,6 +2,10 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** +To test the recent GUI from the main branch, insecure CI artifacts can be used: +- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) +- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) + This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. # Goals and Limitations From c8284f0c323fef61a43efcacca2856043ee12d37 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 13:11:37 +0300 Subject: [PATCH 040/979] qml: Replace QtQuick.Dialogs with QtQuick.Controls 2 Dialog Rebased-From: 4734e5addeb214e4398091b76823b21ffad9ca6d Github-Pull: bitcoin-core/gui-qml#77 --- src/qml/README.md | 4 -- src/qml/bitcoin_qml.qrc | 2 - src/qml/components/BlockCounter.qml | 2 +- src/qml/components/ConnectionOptions.qml | 35 ------------ src/qml/controls/OptionButton.qml | 73 ------------------------ src/qml/doc/icon-policy.md | 39 ------------- src/qml/pages/initerrormessage.qml | 24 +++++--- src/qml/pages/stub.qml | 36 ++++++------ 8 files changed, 35 insertions(+), 180 deletions(-) delete mode 100644 src/qml/components/ConnectionOptions.qml delete mode 100644 src/qml/controls/OptionButton.qml delete mode 100644 src/qml/doc/icon-policy.md diff --git a/src/qml/README.md b/src/qml/README.md index 22b0b90074..a6a8dd5007 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,10 +2,6 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) - This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. # Goals and Limitations diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 35af36ddb5..0cfcef47ef 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -1,8 +1,6 @@ components/BlockCounter.qml - components/ConnectionOptions.qml - controls/OptionButton.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index daefc91e52..69ce238775 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -18,6 +18,6 @@ Label { verticalAlignment: Text.AlignVCenter font.family: "Inter" font.styleName: "Semi Bold" - font.pixelSize: 20 + font.pixelSize: height / 3 text: blockHeight } diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml deleted file mode 100644 index f0d315f7b9..0000000000 --- a/src/qml/components/ConnectionOptions.qml +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2021 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 -import "../controls" - -ColumnLayout { - ButtonGroup { - id: group - } - spacing: 15 - OptionButton { - ButtonGroup.group: group - Layout.fillWidth: true - text: qsTr("Fast always on") - description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") - recommended: true - } - OptionButton { - ButtonGroup.group: group - Layout.fillWidth: true - checked: true - text: qsTr("Slow always on") - description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") - } - OptionButton { - ButtonGroup.group: group - Layout.fillWidth: true - text: qsTr("Only when on Wi-Fi") - description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") - } -} diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml deleted file mode 100644 index 91281077d3..0000000000 --- a/src/qml/controls/OptionButton.qml +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2021 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 - -Button { - property string description - property bool recommended: false - id: button - padding: 15 - checkable: true - background: Rectangle { - border.width: 1 - border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" - radius: 10 - color: "transparent" - Rectangle { - visible: button.visualFocus - anchors.fill: parent - anchors.margins: -4 - border.width: 2 - border.color: "#F7931A" - radius: 14 - color: "transparent" - opacity: 0.4 - } - } - contentItem: ColumnLayout { - spacing: 3 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: 18 - color: "white" - text: button.text - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 15 - color: "#DEDEDE" - text: button.description - wrapMode: Text.WordWrap - } - Loader { - Layout.topMargin: 2 - active: button.recommended - visible: active - sourceComponent: Label { - background: Rectangle { - color: "white" - radius: 3 - } - font.styleName: "Regular" - font.pixelSize: 13 - topPadding: 3 - rightPadding: 7 - bottomPadding: 4 - leftPadding: 7 - color: "black" - text: qsTr("Recommended") - } - } - } -} diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md deleted file mode 100644 index 2152f0bde6..0000000000 --- a/src/qml/doc/icon-policy.md +++ /dev/null @@ -1,39 +0,0 @@ -# Icon policy -This document provides guidelines for contributing icons to Bitcoin Core. - -## Preparing Icons -Both an icon source file, in Scalable Vector Graphics (SVG) format, -and an optimized production file, in Portable Network Graphics (PNG) format, -are required for each icon. - -#### SVG Source File -SVGs are used as source files because they can scale while retaining image quality. -They are not used in production due to limited application support. -If different-sized production (PNG) icons are required, -they can be generated from the associated SVG source file in any vector-based tool. - -#### PNG Production File -PNGs are used in production due to wide application support, transparency support, -and better image quality compared to competing file types such as JPEG. - -#### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. -PNG optimization removes various unnecessary color profiles, ancillary data, -and text chunks, resulting in a lossless file size reduction. - -## Contributing -Bitcoin Core primarily uses icons from the [Bitcoin Icon set](https://github.com/BitcoinDesign/Bitcoin-Icons), -an open source icon set made for Bitcoin applications. -If a proposed feature requires an icon to be designed, -an issue should be opened in the [Bitcoin Icons repo](https://github.com/BitcoinDesign/Bitcoin-Icons/issues) -with the request. - -Icons are not to be added to Bitcoin Core prior to a production use case. -If an icon is not being used, it should be removed. - -SVGs are to be included under the `src/qml/res/src` directory. -Optimized PNGs are to be included under the `src/qml/res/icons` directory. - -## Attribution -Icon additions must include appropriate attribution to the author, license information, and any comments relevant to the icon documented under the -[contrib/debian/copyright](../../../contrib/debian/copyright) file. diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index f305993dc3..e9d4ed8cb0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -3,13 +3,23 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. import QtQuick 2.12 -import QtQuick.Dialogs 1.3 +import QtQuick.Controls 2.12 -MessageDialog { - id: messageDialog +ApplicationWindow { title: "Bitcoin Core TnG" - icon: StandardIcon.Critical - text: message - onAccepted: Qt.quit() - Component.onCompleted: visible = true + visible: true + minimumWidth: 500 + minimumHeight: 200 + + Dialog { + anchors.centerIn: parent + title: qsTr("Error") + contentItem: + Label { + text: message + } + visible: true + standardButtons: Dialog.Ok + onAccepted: Qt.quit() + } } diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..cdee0fd0ce 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,35 +5,33 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: "black" + background: Rectangle { + color: "black" + } visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); - ColumnLayout { + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + + BitcoinCoreComponents.BlockCounter { + id: blockCounter anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } + height: parent.height / 3 + blockHeight: nodeModel.blockTipHeight } } From 7d674143dbf6b6f6f55510be9edd82e93903e69a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 13:59:58 +0300 Subject: [PATCH 041/979] Revert "build, qml: Add qtquickcontrols module" This reverts commit f88cc244a3fe4a58a2a5d25822f3c097b4b0facc. Rebased-From: 48fb72488a41083af8b9d460300981029d1fd2f4 Github-Pull: bitcoin-core/gui-qml#77 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 795bb230b1..5e035677dd 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -42,10 +42,8 @@ QT_END_NAMESPACE #if defined(QT_STATICPLUGIN) #include -Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); From 920c6ac251b00895e40d9b3a80926de0a631b019 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:17:44 +0300 Subject: [PATCH 042/979] doc: Drop unneeded runtime dependencies Rebased-From: 7dc95a00688c8f341496991626400b5909ccac25 Github-Pull: bitcoin-core/gui-qml#77 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index a6a8dd5007..7dbee86fd7 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -51,7 +51,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. From 0ccbe30297fb96ada469fc2d6f1d96a93d1cf39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:38:39 +0100 Subject: [PATCH 043/979] qml: Use window color instead of background Follow Qt recomendation (1) since the background is a solid color. 1. https://doc.qt.io/qt-5/qml-qtquick-controls2-applicationwindow.html#background-prop Rebased-From: cd5527f6951c1f3eed2466abefbb007785d2ab14 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/doc/icon-policy.md | 39 -------------------------------------- src/qml/pages/stub.qml | 4 +--- 2 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 src/qml/doc/icon-policy.md diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md deleted file mode 100644 index 2152f0bde6..0000000000 --- a/src/qml/doc/icon-policy.md +++ /dev/null @@ -1,39 +0,0 @@ -# Icon policy -This document provides guidelines for contributing icons to Bitcoin Core. - -## Preparing Icons -Both an icon source file, in Scalable Vector Graphics (SVG) format, -and an optimized production file, in Portable Network Graphics (PNG) format, -are required for each icon. - -#### SVG Source File -SVGs are used as source files because they can scale while retaining image quality. -They are not used in production due to limited application support. -If different-sized production (PNG) icons are required, -they can be generated from the associated SVG source file in any vector-based tool. - -#### PNG Production File -PNGs are used in production due to wide application support, transparency support, -and better image quality compared to competing file types such as JPEG. - -#### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. -PNG optimization removes various unnecessary color profiles, ancillary data, -and text chunks, resulting in a lossless file size reduction. - -## Contributing -Bitcoin Core primarily uses icons from the [Bitcoin Icon set](https://github.com/BitcoinDesign/Bitcoin-Icons), -an open source icon set made for Bitcoin applications. -If a proposed feature requires an icon to be designed, -an issue should be opened in the [Bitcoin Icons repo](https://github.com/BitcoinDesign/Bitcoin-Icons/issues) -with the request. - -Icons are not to be added to Bitcoin Core prior to a production use case. -If an icon is not being used, it should be removed. - -SVGs are to be included under the `src/qml/res/src` directory. -Optimized PNGs are to be included under the `src/qml/res/icons` directory. - -## Attribution -Icon additions must include appropriate attribution to the author, license information, and any comments relevant to the icon documented under the -[contrib/debian/copyright](../../../contrib/debian/copyright) file. diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index cdee0fd0ce..ac4f514c84 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,9 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - background: Rectangle { - color: "black" - } + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); From de9463154b5ef99c0526f48af77fdea41fcfc68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:37:00 +0100 Subject: [PATCH 044/979] qml: Remove explicit height of BlockCounter Label implicit height depends on the font size but the font size depends on the label height. This results in a runtime anchor loop warning. Rebased-From: 6bedd3de45e236b3fb6d23dbb07a84cad17d68a4 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/components/BlockCounter.qml | 2 +- src/qml/pages/stub.qml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 69ce238775..daefc91e52 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -18,6 +18,6 @@ Label { verticalAlignment: Text.AlignVCenter font.family: "Inter" font.styleName: "Semi Bold" - font.pixelSize: height / 3 + font.pixelSize: 20 text: blockHeight } diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ac4f514c84..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -29,7 +29,6 @@ ApplicationWindow { BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent - height: parent.height / 3 blockHeight: nodeModel.blockTipHeight } } From 797129688333a4050ede7798f4effdc18a85d210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:10:14 +0100 Subject: [PATCH 045/979] qml: Drop import qualifier BitcoinCoreComponents Rebased-From: 5b006120136aa6e06921b96dffdad9ab16012e20 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/pages/stub.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,8 +5,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" as BitcoinCoreComponents - +import "../components" ApplicationWindow { id: appWindow @@ -26,7 +25,7 @@ ApplicationWindow { sourceSize.height: 128 } - BitcoinCoreComponents.BlockCounter { + BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From 6e59b134c8795aafd3ce6be8842a2d1bf7466c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:44:47 +0100 Subject: [PATCH 046/979] qml: Use ColumnLayout in application window Rebased-From: 37cfe4e71cbb7ecffa3e03d5b3908842fdaf33de Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/pages/stub.qml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,17 +17,19 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - Image { - id: appLogo - anchors.horizontalCenter: parent.horizontalCenter - source: "image://images/app" - sourceSize.width: 128 - sourceSize.height: 128 - } - - BlockCounter { - id: blockCounter + ColumnLayout { anchors.centerIn: parent - blockHeight: nodeModel.blockTipHeight + spacing: 15 + width: 400 + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } } } From 811ec409d229facccc8d3dd0928321ef3d4bebaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 12:00:48 +0100 Subject: [PATCH 047/979] qml: Add OptionButton control Rebased-From: cbe91f61c50d08b3b6db332419268a036fbb2bc1 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/bitcoin_qml.qrc | 2 + src/qml/controls/OptionButton.qml | 73 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/qml/controls/OptionButton.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 0cfcef47ef..35af36ddb5 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -1,6 +1,8 @@ components/BlockCounter.qml + components/ConnectionOptions.qml + controls/OptionButton.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml new file mode 100644 index 0000000000..91281077d3 --- /dev/null +++ b/src/qml/controls/OptionButton.qml @@ -0,0 +1,73 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 + +Button { + property string description + property bool recommended: false + id: button + padding: 15 + checkable: true + background: Rectangle { + border.width: 1 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" + radius: 10 + color: "transparent" + Rectangle { + visible: button.visualFocus + anchors.fill: parent + anchors.margins: -4 + border.width: 2 + border.color: "#F7931A" + radius: 14 + color: "transparent" + opacity: 0.4 + } + } + contentItem: ColumnLayout { + spacing: 3 + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pointSize: 18 + color: "white" + text: button.text + wrapMode: Text.WordWrap + } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: 15 + color: "#DEDEDE" + text: button.description + wrapMode: Text.WordWrap + } + Loader { + Layout.topMargin: 2 + active: button.recommended + visible: active + sourceComponent: Label { + background: Rectangle { + color: "white" + radius: 3 + } + font.styleName: "Regular" + font.pixelSize: 13 + topPadding: 3 + rightPadding: 7 + bottomPadding: 4 + leftPadding: 7 + color: "black" + text: qsTr("Recommended") + } + } + } +} From 006f890f3a44d8548403af6ff7103bf53a6aced8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 18:18:13 +0100 Subject: [PATCH 048/979] qml: Add ConnectionOptions component Rebased-From: 7985aadefb844157de78c8a2c1717533bc2b2947 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/components/ConnectionOptions.qml | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/qml/components/ConnectionOptions.qml diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml new file mode 100644 index 0000000000..f0d315f7b9 --- /dev/null +++ b/src/qml/components/ConnectionOptions.qml @@ -0,0 +1,35 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 +import "../controls" + +ColumnLayout { + ButtonGroup { + id: group + } + spacing: 15 + OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + text: qsTr("Fast always on") + description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") + recommended: true + } + OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + checked: true + text: qsTr("Slow always on") + description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") + } + OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + text: qsTr("Only when on Wi-Fi") + description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") + } +} From e886bbc469c60ae7de4a764cdf6437ca8c09e1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:46:48 +0100 Subject: [PATCH 049/979] qml: Show ConnectionOptions Rebased-From: 61668e989adc3fc53431665fddf4fd1f19926391 Github-Pull: bitcoin-core/gui-qml#67 --- src/qml/pages/stub.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,5 +31,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ConnectionOptions { + Layout.preferredWidth: 400 + focus: true + } } } From ac1b32a8a1e01cd63a39efc3c437239c0cacbd4e Mon Sep 17 00:00:00 2001 From: bosch Date: Sat, 9 Jan 2021 14:22:42 +0800 Subject: [PATCH 050/979] doc: introduce icon policy documentation Rebased-From: 7335bdd22b0c7a0cbc040a4df373c67fb7e776d6 Github-Pull: bitcoin-core/gui-qml#70 --- src/qml/README.md | 4 ---- src/qml/bitcoin.cpp | 8 +++++--- src/qml/doc/icon-policy.md | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 src/qml/doc/icon-policy.md diff --git a/src/qml/README.md b/src/qml/README.md index 22b0b90074..a6a8dd5007 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,10 +2,6 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) - This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. # Goals and Limitations diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 795bb230b1..425b8fb2cf 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE @@ -98,17 +98,19 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md new file mode 100644 index 0000000000..2152f0bde6 --- /dev/null +++ b/src/qml/doc/icon-policy.md @@ -0,0 +1,39 @@ +# Icon policy +This document provides guidelines for contributing icons to Bitcoin Core. + +## Preparing Icons +Both an icon source file, in Scalable Vector Graphics (SVG) format, +and an optimized production file, in Portable Network Graphics (PNG) format, +are required for each icon. + +#### SVG Source File +SVGs are used as source files because they can scale while retaining image quality. +They are not used in production due to limited application support. +If different-sized production (PNG) icons are required, +they can be generated from the associated SVG source file in any vector-based tool. + +#### PNG Production File +PNGs are used in production due to wide application support, transparency support, +and better image quality compared to competing file types such as JPEG. + +#### Optimizing Production Files (PNG) +Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. +PNG optimization removes various unnecessary color profiles, ancillary data, +and text chunks, resulting in a lossless file size reduction. + +## Contributing +Bitcoin Core primarily uses icons from the [Bitcoin Icon set](https://github.com/BitcoinDesign/Bitcoin-Icons), +an open source icon set made for Bitcoin applications. +If a proposed feature requires an icon to be designed, +an issue should be opened in the [Bitcoin Icons repo](https://github.com/BitcoinDesign/Bitcoin-Icons/issues) +with the request. + +Icons are not to be added to Bitcoin Core prior to a production use case. +If an icon is not being used, it should be removed. + +SVGs are to be included under the `src/qml/res/src` directory. +Optimized PNGs are to be included under the `src/qml/res/icons` directory. + +## Attribution +Icon additions must include appropriate attribution to the author, license information, and any comments relevant to the icon documented under the +[contrib/debian/copyright](../../../contrib/debian/copyright) file. From 44e157fcb38fa0ad73d5b95ec5c2d80810379d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:47:30 +0100 Subject: [PATCH 051/979] qml: Add ProgressIndicator control Rebased-From: 455b2f8d7b9a3caea5b2a36391a562643cf6ffd4 Github-Pull: bitcoin-core/gui-qml#69 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 2 ++ src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/ProgressIndicator.qml | 33 ++++++++++++++++++++++++++ src/qml/pages/initerrormessage.qml | 24 ++++++------------- 5 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 src/qml/controls/ProgressIndicator.qml diff --git a/src/qml/README.md b/src/qml/README.md index 7b8217221a..22b0b90074 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -55,7 +55,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 5e035677dd..795bb230b1 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -42,8 +42,10 @@ QT_END_NAMESPACE #if defined(QT_STATICPLUGIN) #include +Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 35af36ddb5..043d81bba0 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -3,6 +3,7 @@ components/BlockCounter.qml components/ConnectionOptions.qml controls/OptionButton.qml + controls/ProgressIndicator.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml new file mode 100644 index 0000000000..c58f402738 --- /dev/null +++ b/src/qml/controls/ProgressIndicator.qml @@ -0,0 +1,33 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +Control { + property real progress: 0 + Behavior on progress { + NumberAnimation { + easing.type: Easing.Bezier + easing.bezierCurve: [0.5, 0.0, 0.2, 1, 1, 1] + duration: 250 + } + } + contentItem: Rectangle { + implicitHeight: 6 + radius: Math.floor(height / 2) + color: "#404040" + Item { + width: Math.round(progress * contentItem.width) + height: parent.height + clip: true + Rectangle { + width: contentItem.width + height: contentItem.height + radius: contentItem.radius + color: "orange" + } + } + } +} diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index e9d4ed8cb0..f305993dc3 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -3,23 +3,13 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick.Dialogs 1.3 -ApplicationWindow { +MessageDialog { + id: messageDialog title: "Bitcoin Core TnG" - visible: true - minimumWidth: 500 - minimumHeight: 200 - - Dialog { - anchors.centerIn: parent - title: qsTr("Error") - contentItem: - Label { - text: message - } - visible: true - standardButtons: Dialog.Ok - onAccepted: Qt.quit() - } + icon: StandardIcon.Critical + text: message + onAccepted: Qt.quit() + Component.onCompleted: visible = true } From 9f48c1b7f22c244ab08ffd51561b1dbbf5651c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:48:06 +0100 Subject: [PATCH 052/979] qml: Demo ProgressIndicator control Rebased-From: 1bf3d5d9287a0296b2d2af5cd690bab029f803f2 Github-Pull: bitcoin-core/gui-qml#69 --- src/qml/pages/stub.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,6 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" +import "../controls" ApplicationWindow { id: appWindow @@ -31,6 +32,14 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ProgressIndicator { + id: indicator + Layout.fillWidth: true + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } + } ConnectionOptions { Layout.preferredWidth: 400 focus: true From b591b57feee5819c0b4fe19498cd4905cfb5ee1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 3 Nov 2021 17:43:08 +0000 Subject: [PATCH 053/979] ci: Set alias in tasks with artifacts in cirrus.yml Rebased-From: 011fcfff722982e20fc9a7ba39d276e71d8e585e Github-Pull: bitcoin-core/gui-qml#79 --- src/qml/README.md | 4 ++-- src/qml/bitcoin_qml.qrc | 1 - src/qml/controls/ProgressIndicator.qml | 33 -------------------------- src/qml/pages/stub.qml | 9 ------- 4 files changed, 2 insertions(+), 45 deletions(-) delete mode 100644 src/qml/controls/ProgressIndicator.qml diff --git a/src/qml/README.md b/src/qml/README.md index 7b8217221a..9c46acb8e5 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -3,8 +3,8 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) +- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) +- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 043d81bba0..35af36ddb5 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -3,7 +3,6 @@ components/BlockCounter.qml components/ConnectionOptions.qml controls/OptionButton.qml - controls/ProgressIndicator.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml deleted file mode 100644 index c58f402738..0000000000 --- a/src/qml/controls/ProgressIndicator.qml +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2021 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -Control { - property real progress: 0 - Behavior on progress { - NumberAnimation { - easing.type: Easing.Bezier - easing.bezierCurve: [0.5, 0.0, 0.2, 1, 1, 1] - duration: 250 - } - } - contentItem: Rectangle { - implicitHeight: 6 - radius: Math.floor(height / 2) - color: "#404040" - Item { - width: Math.round(progress * contentItem.width) - height: parent.height - clip: true - Rectangle { - width: contentItem.width - height: contentItem.height - radius: contentItem.radius - color: "orange" - } - } - } -} diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 10e398815a55adf4d4fa56f0fb977c6eff29eb42 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 3 Nov 2021 21:38:28 -0400 Subject: [PATCH 054/979] doc: introduce translator comment policy documentation Rebased-From: a4fd76f47f290e2cfb21d040383409d9ac30be81 Github-Pull: bitcoin-core/gui-qml#81 --- src/qml/README.md | 4 +- src/qml/bitcoin_qml.qrc | 1 - src/qml/controls/ProgressIndicator.qml | 33 ---------- src/qml/doc/translator-comments.md | 86 ++++++++++++++++++++++++++ src/qml/pages/stub.qml | 9 --- 5 files changed, 88 insertions(+), 45 deletions(-) delete mode 100644 src/qml/controls/ProgressIndicator.qml create mode 100644 src/qml/doc/translator-comments.md diff --git a/src/qml/README.md b/src/qml/README.md index 9c46acb8e5..7b8217221a 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -3,8 +3,8 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) +- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 043d81bba0..35af36ddb5 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -3,7 +3,6 @@ components/BlockCounter.qml components/ConnectionOptions.qml controls/OptionButton.qml - controls/ProgressIndicator.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml deleted file mode 100644 index c58f402738..0000000000 --- a/src/qml/controls/ProgressIndicator.qml +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2021 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -Control { - property real progress: 0 - Behavior on progress { - NumberAnimation { - easing.type: Easing.Bezier - easing.bezierCurve: [0.5, 0.0, 0.2, 1, 1, 1] - duration: 250 - } - } - contentItem: Rectangle { - implicitHeight: 6 - radius: Math.floor(height / 2) - color: "#404040" - Item { - width: Math.round(progress * contentItem.width) - height: parent.height - clip: true - Rectangle { - width: contentItem.width - height: contentItem.height - radius: contentItem.radius - color: "orange" - } - } - } -} diff --git a/src/qml/doc/translator-comments.md b/src/qml/doc/translator-comments.md new file mode 100644 index 0000000000..3558dabb6d --- /dev/null +++ b/src/qml/doc/translator-comments.md @@ -0,0 +1,86 @@ +# Translator Comment Policy + +Translator comments are required for all user-facing strings. A PR introducing +new user-facing strings must also submit the accompanying translator comment. +To prevent this requirement from halting development, the PR author can specify +that they would like the introduction of the comment to be picked up in a +follow-up PR. + +## Formulating Translator Comments + +Translator comments only apply to strings that are marked for translation. +For more information, see: +[Internationalization and Localization with Qt Quick](https://doc.qt.io/qt-5/qtquick-internationalization.html) + +Below, the values for the `text` and `description` properties are examples of +new user-facing strings marked for translation without translator comments: + +```qml +OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + text: qsTr("Only when on Wi-Fi") + description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") +} +``` + +Translator comments are needed to provide a translator with the appropriate +context needed to aid them with translating a certain string. +The first step in formulating a translator comment is to think about what +information a translator needs to perform their job effectively. + +**Necessary context is**: +- Where is this string shown? + - e.g. Shown in the Create Wallet dialog, Shown in file menu options ... +- Explain what the string is meant to convey + - This is an explanatory text shown after X that aims to inform the user that ... +- What action is associated with this string? + - If the string is associated with a button, what is the outcome of pressing the button? + +**Optional context is**: +- Alternatives to complicated/technical words + - Some words may not have a direct one-to-one translation in certain languages. + It is nice to provide a replacement for such a word. For example, + some languages may not have a 1-1 translation for the word "subnet", + an appropriate substitute for this word is "IP address". + +## Writing Translator Comments + +Begin by writing down the text for the comment, guided by the necessary and +optional context specified in the previous section. Ensure that your text ends +in a full stop. + +For the value of the `text` property, you may write: + +> Main text for button displayed when choosing the network mode the client will +run in. Choosing this option means that the node will only sync when the device +is connected to a wireless internet connection. + +For the value of the `description` property, you may write: + +> Explanatory text for button which allows user to set the client to only load +when connected to wifi. This text intends to make it clear to the user that, +under this mode, their node will not sync if connected to cellular data. +If there is no clear translation for "cellular data", use the translation for +"mobile data". + +Now take these texts, split them into separate sentences, and append `//:` +to them. Place the text above its respective translatable string: + +```qml +OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + //: Main text for button displayed when choosing the network mode the client will run in. + //: Choosing this option means that the node will only sync when the device is connected to a wireless internet connection. + text: qsTr("Only when on Wi-Fi") + //: Explanatory text for button which allows user to set the client to only load when connected to wifi. + //: This text intends to make it clear to the user that, under this mode, their node will not sync if connected to cellular data. + //: If there is no clear translation for "cellular data", use the translation for "mobile data". + description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") +} +``` + +The special character `//:` lets Qt's translator engine know that the proceeding +text is a translator comment. Each line will get concatenated together to be +presented to the translator as one paragraph. diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From e880fc383e93418033c54176c34af8259e3ef7b9 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 6 Nov 2021 12:09:06 +0200 Subject: [PATCH 055/979] doc: Add a link to Android APK CI artifact to README and PR template Rebased-From: 83f1893265bfa9b45dfc08cd2cf6d91c451e213d Github-Pull: bitcoin-core/gui-qml#82 --- src/qml/README.md | 1 + src/qml/doc/translator-comments.md | 86 ------------------------------ 2 files changed, 1 insertion(+), 86 deletions(-) delete mode 100644 src/qml/doc/translator-comments.md diff --git a/src/qml/README.md b/src/qml/README.md index 9c46acb8e5..466066a23f 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -5,6 +5,7 @@ To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. diff --git a/src/qml/doc/translator-comments.md b/src/qml/doc/translator-comments.md deleted file mode 100644 index 3558dabb6d..0000000000 --- a/src/qml/doc/translator-comments.md +++ /dev/null @@ -1,86 +0,0 @@ -# Translator Comment Policy - -Translator comments are required for all user-facing strings. A PR introducing -new user-facing strings must also submit the accompanying translator comment. -To prevent this requirement from halting development, the PR author can specify -that they would like the introduction of the comment to be picked up in a -follow-up PR. - -## Formulating Translator Comments - -Translator comments only apply to strings that are marked for translation. -For more information, see: -[Internationalization and Localization with Qt Quick](https://doc.qt.io/qt-5/qtquick-internationalization.html) - -Below, the values for the `text` and `description` properties are examples of -new user-facing strings marked for translation without translator comments: - -```qml -OptionButton { - ButtonGroup.group: group - Layout.fillWidth: true - text: qsTr("Only when on Wi-Fi") - description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") -} -``` - -Translator comments are needed to provide a translator with the appropriate -context needed to aid them with translating a certain string. -The first step in formulating a translator comment is to think about what -information a translator needs to perform their job effectively. - -**Necessary context is**: -- Where is this string shown? - - e.g. Shown in the Create Wallet dialog, Shown in file menu options ... -- Explain what the string is meant to convey - - This is an explanatory text shown after X that aims to inform the user that ... -- What action is associated with this string? - - If the string is associated with a button, what is the outcome of pressing the button? - -**Optional context is**: -- Alternatives to complicated/technical words - - Some words may not have a direct one-to-one translation in certain languages. - It is nice to provide a replacement for such a word. For example, - some languages may not have a 1-1 translation for the word "subnet", - an appropriate substitute for this word is "IP address". - -## Writing Translator Comments - -Begin by writing down the text for the comment, guided by the necessary and -optional context specified in the previous section. Ensure that your text ends -in a full stop. - -For the value of the `text` property, you may write: - -> Main text for button displayed when choosing the network mode the client will -run in. Choosing this option means that the node will only sync when the device -is connected to a wireless internet connection. - -For the value of the `description` property, you may write: - -> Explanatory text for button which allows user to set the client to only load -when connected to wifi. This text intends to make it clear to the user that, -under this mode, their node will not sync if connected to cellular data. -If there is no clear translation for "cellular data", use the translation for -"mobile data". - -Now take these texts, split them into separate sentences, and append `//:` -to them. Place the text above its respective translatable string: - -```qml -OptionButton { - ButtonGroup.group: group - Layout.fillWidth: true - //: Main text for button displayed when choosing the network mode the client will run in. - //: Choosing this option means that the node will only sync when the device is connected to a wireless internet connection. - text: qsTr("Only when on Wi-Fi") - //: Explanatory text for button which allows user to set the client to only load when connected to wifi. - //: This text intends to make it clear to the user that, under this mode, their node will not sync if connected to cellular data. - //: If there is no clear translation for "cellular data", use the translation for "mobile data". - description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") -} -``` - -The special character `//:` lets Qt's translator engine know that the proceeding -text is a translator comment. Each line will get concatenated together to be -presented to the translator as one paragraph. From 264615b5e49da611fe09e05b03802081709333fd Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:02:36 -0500 Subject: [PATCH 056/979] Revert "doc: Add a link to Android APK CI artifact to README and PR template" This reverts commit 80ded50950f910879765cdfdabe87fdc71f68e6e. Rebased-From: ec5962390318ea958fda1da89ebc0bb93110ff98 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 466066a23f..9c46acb8e5 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -5,7 +5,6 @@ To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) -- for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. From c8683cd64035067b2b6699108c57e74c1fec44a1 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:04:13 -0500 Subject: [PATCH 057/979] Revert "ci: Set alias in tasks with artifacts in cirrus.yml" This reverts commit 8d5ea7cdbacf05015fa73d725d60d541f23bd366. Rebased-From: eb93d9afb7147238b87321c2a35243fa227b818b Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 9c46acb8e5..7b8217221a 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -3,8 +3,8 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) +- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. From 97486ea2488cfd675fd993ac69a4da4b96cbb411 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:05:51 -0500 Subject: [PATCH 058/979] Revert "qml: Demo ProgressIndicator control" This reverts commit 1ae2e09b0cedb8e2c52de476058e96f3d755e11e. Rebased-From: f7ab30cdcb374a17cd3674c92f644145534342c1 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From feb2f90aa5178c3c931ae1941d636d99cbd6de3d Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:39:16 -0500 Subject: [PATCH 059/979] Revert "doc: Drop unneeded runtime dependencies" This reverts commit 871de3f4541cb074ba0479bcf1bda5d2e2ec9402. Rebased-From: 6187849cf3d8c962363092b619b62e8a09c1ade0 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 7b8217221a..22b0b90074 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -55,7 +55,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. From 221adc397c2aeb0695798666df148eb83e13b740 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:39:36 -0500 Subject: [PATCH 060/979] Revert "Revert "build, qml: Add qtquickcontrols module"" This reverts commit fdc721225c13c4d3b03812ee9777083f6290e9d8. Rebased-From: e7f798577d84360c009df1ff5574257cbae76e69 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 5e035677dd..795bb230b1 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -42,8 +42,10 @@ QT_END_NAMESPACE #if defined(QT_STATICPLUGIN) #include +Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); From efcc67499d64cc8124173c1a3c7cbe888f08d4f0 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:41:37 -0500 Subject: [PATCH 061/979] Revert "qml: Show ConnectionOptions" This reverts commit 22b2f0a2771e2f6303b6d5668bce82dfbc499b08. Rebased-From: b2916addc4170955e38734764ff6d62dd68ac4be Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,9 +31,5 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } } } From b108b4204337cdfd1edc4ac8ce98ddd9e6a04bf2 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:42:04 -0500 Subject: [PATCH 062/979] Revert "qml: Use ColumnLayout in application window" This reverts commit c948bc090e882082681a559770ed22daf046817c. Rebased-From: 50d5f757e1e18d0cafccc85f4b85297459450939 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,19 +17,17 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - ColumnLayout { + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + + BlockCounter { + id: blockCounter anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } + blockHeight: nodeModel.blockTipHeight } } From b70447535f1b38e17d6ef3e7721d192c3dbdf27c Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 15:42:17 -0500 Subject: [PATCH 063/979] Revert "qml: Drop import qualifier BitcoinCoreComponents" This reverts commit d72de3a2ca42ec9508783755036752bfbfbde615. Rebased-From: 98a4d9d002e03cdfc56cc98264035fe6f76d5f0e Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,7 +5,8 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow @@ -25,7 +26,7 @@ ApplicationWindow { sourceSize.height: 128 } - BlockCounter { + BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From 03fa100e625f9e5d6feb9efb376a64021473fc76 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 16:08:53 -0500 Subject: [PATCH 064/979] Revert "qml: Set tab focus behavior" This reverts commit c386fbfe6c1a10b14d9e14cf0d485b07f3a3c198. Rebased-From: 48f87587036ea366a27e8763acc7a5cfa9e56681 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 795bb230b1..4b02e2ea86 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE @@ -98,7 +97,6 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 0dfde0b506e2a2b1c5a179a1d11f4c216b19f518 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 16:17:36 -0500 Subject: [PATCH 065/979] Revert "multiprocess: add new bitcoin-qt init implementation to qml-gui" This reverts commit a7028eea93e40fd657a79488f46f1a282c9e2cf1. Rebased-From: 19d4b8fe8fbd1e9cbd17101d9285592cd09a2fdf Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4b02e2ea86..425b8fb2cf 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -101,12 +102,15 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 319c90acfc0ed13b27e39baf60187d66f162bf01 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 16:18:36 -0500 Subject: [PATCH 066/979] Revert "qml: Drop erroneous `#include `" This reverts commit 15ee3f4f2b5c4506e9bfece86fe8df91ac95ac91. Rebased-From: a2d5d9f8b8ffd5da8ed25a4fe59065892ee97c69 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 425b8fb2cf..f454fdb0c7 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE From 32ab3c050a82c03efbe33c33a2129634727de965 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 19:28:37 -0500 Subject: [PATCH 067/979] Revert "qml, build, doc: Allow import QtQuick.Layouts" This reverts commit b431cefac446cc4048da0e3d458b07f162f09c52. Rebased-From: c4c57b7ed08c25f14da2ae7e4ae422671e7130f6 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 - src/qml/pages/stub.qml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 22b0b90074..1cd3ba01cd 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -55,7 +55,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index f454fdb0c7..ed4461cf99 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -48,7 +48,6 @@ Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls1Plugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..7a56f6ce3a 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,7 +4,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From 4ab85d0633ddc59af88da0db8fdc30521d50a404 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 19:29:04 -0500 Subject: [PATCH 068/979] Revert "qml: Add qInstallMessageHandler" This reverts commit 4f1a5d7098d425125e88f5d8d5e3deb98c215fbe. Rebased-From: 28ae857569bb490f8b2272c56c4e08e032aefc03 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index ed4461cf99..7567cd9440 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -33,14 +32,9 @@ #include #include #include -#include #include #include -QT_BEGIN_NAMESPACE -class QMessageLogContext; -QT_END_NAMESPACE - #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); @@ -74,17 +68,6 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } - -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); - } -} } // namespace @@ -196,9 +179,6 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); - qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); From a89f4ba178955e0a79a0561e3ea07895a2949e14 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 19:30:10 -0500 Subject: [PATCH 069/979] Revert "build, qml: Add qtquickcontrols2 module" This reverts commit ae722498225199b2fbe3af952be872300715f61d. Rebased-From: 5f8697954332f813825c881b71cffbcc672892e8 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7567cd9440..090325548f 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,8 +41,6 @@ Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls1Plugin); -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From cc91468b65c6a858ca6a3c47838e0f725c73b67c Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 19:30:25 -0500 Subject: [PATCH 070/979] Revert "build, qml: Add qtquickcontrols module" This reverts commit f88cc244a3fe4a58a2a5d25822f3c097b4b0facc. Rebased-From: 9837d0b306ec07be1b2e3ab6b1ab653e3257ff4d Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 090325548f..814baa4e2e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -37,10 +37,8 @@ #if defined(QT_STATICPLUGIN) #include -Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin); Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -Q_IMPORT_PLUGIN(QtQuickControls1Plugin); #endif namespace { From b0aa30d01dcb8f7425d88795760ea7d5d0363d28 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Tue, 30 Nov 2021 19:31:02 -0500 Subject: [PATCH 071/979] Revert "build, qml: Add qtdeclarative module" This reverts commit 29370597d79a7cbff40621e8220574468d316965. Rebased-From: b235dd5dba278116704b57a475d3e3369ccfa66e Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 814baa4e2e..9bd18f302c 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,12 +35,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQuick2Plugin); -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { From 029b362d3b39a5efd184122f5425cec2f12d8a80 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:50:48 +0300 Subject: [PATCH 072/979] build, qml: Add qtdeclarative module Rebased-From: 3e46c0659179c54e5b3e3a999ca6f606254a15d4 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9bd18f302c..814baa4e2e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,6 +35,12 @@ #include #include +#if defined(QT_STATICPLUGIN) +#include +Q_IMPORT_PLUGIN(QtQuick2Plugin); +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +#endif + namespace { void SetupUIArgs(ArgsManager& argsman) { From 90d30c2c78952555280dad38e7fc3f4ddf489c25 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:54:11 +0300 Subject: [PATCH 073/979] build, qml: Add qtquickcontrols2 module Rebased-From: ccb193d3ed15bc3db0f323271a698e80d45401d5 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 814baa4e2e..6b6adb7c34 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -39,6 +39,8 @@ #include Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); +Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From f9c2d0362f6e09d782364b7b811b0dc6f5f6f0ae Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:13:33 +0300 Subject: [PATCH 074/979] qml: Add qInstallMessageHandler Rebased-From: e297bee60dba7cb780a21d6af996fe4747c66ffa Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 6b6adb7c34..57e7193ec4 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,14 @@ #include #include #include +#include #include #include +QT_BEGIN_NAMESPACE +class QMessageLogContext; +QT_END_NAMESPACE + #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQuick2Plugin); @@ -66,6 +72,17 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } + +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } +} } // namespace @@ -177,6 +194,9 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + // Install qDebug() message handler to route to debug.log + qInstallMessageHandler(DebugMessageHandler); + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); From 66f5219730ed6311c8e991a79d26a81fccd24e2a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 3 Oct 2021 14:32:13 +0300 Subject: [PATCH 075/979] qml, build, doc: Allow import QtQuick.Layouts Rebased-From: cdb9844c71acd4901bf83449baf167b16fc1feea Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 + src/qml/pages/stub.qml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 1cd3ba01cd..22b0b90074 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -55,7 +55,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 57e7193ec4..7a64b4f2aa 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -46,6 +46,7 @@ QT_END_NAMESPACE Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 7a56f6ce3a..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,6 +4,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From 51f65076ff30eb0d579b6bbd9bb6929325b394ff Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:33:02 +0300 Subject: [PATCH 076/979] qml: Drop erroneous `#include ` To use the `QStringLiteral` macro, the `QString` header should be included, that is done already. Rebased-From: 6cae8b3592265ff2cae4baffc06b3d70453ba115 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7a64b4f2aa..797c8193c7 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE From 4d2d1c6f0cd6d3b970a163f54b8739ad8a28c7b9 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 27 Oct 2021 14:49:32 -0400 Subject: [PATCH 077/979] multiprocess: add new bitcoin-qt init implementation to qml-gui This incorporates the new bitcoin-qt init implementation into the qml-gui. Rebased-From: 3273800e03cf687bdcabc050f2e4acda2c2db99b Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 797c8193c7..50a9d8f56d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -100,15 +99,12 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 5fd34c085497ad8eaaf45784d3390873a42dd248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:20:03 +0100 Subject: [PATCH 078/979] qml: Set tab focus behavior Rebased-From: 901184f9035e59300387ec19c44b6e128ab8bb35 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 50a9d8f56d..5e035677dd 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -95,6 +96,7 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 472b003ab623636cb982fa531df772bec985d6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:10:14 +0100 Subject: [PATCH 079/979] qml: Drop import qualifier BitcoinCoreComponents Rebased-From: 4c5d834c4c1566ce23caf0761b17e47105bf1ad5 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,8 +5,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" as BitcoinCoreComponents - +import "../components" ApplicationWindow { id: appWindow @@ -26,7 +25,7 @@ ApplicationWindow { sourceSize.height: 128 } - BitcoinCoreComponents.BlockCounter { + BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From a23bf3dbd8ebb4ceb98325cce0cb989edb5445c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:44:47 +0100 Subject: [PATCH 080/979] qml: Use ColumnLayout in application window Rebased-From: a33f314e032f3ded5ae1ef3c6d24c3b79032c23c Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,17 +17,19 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - Image { - id: appLogo - anchors.horizontalCenter: parent.horizontalCenter - source: "image://images/app" - sourceSize.width: 128 - sourceSize.height: 128 - } - - BlockCounter { - id: blockCounter + ColumnLayout { anchors.centerIn: parent - blockHeight: nodeModel.blockTipHeight + spacing: 15 + width: 400 + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } } } From d360ef65396ea4fc461d0b77f7af9d8190722c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:46:48 +0100 Subject: [PATCH 081/979] qml: Show ConnectionOptions Rebased-From: 1863ab4a86502c0985eb0e3d5fef806ddfe7136c Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,5 +31,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ConnectionOptions { + Layout.preferredWidth: 400 + focus: true + } } } From ab88e4e80232af6ec85b3775e775545b28dd1c88 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:17:44 +0300 Subject: [PATCH 082/979] doc: Drop unneeded runtime dependencies Rebased-From: 0daccfd60b38c18b4c5e34b9935f684ee54b8147 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 22b0b90074..7b8217221a 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -55,7 +55,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. From 26dfe531c446784754b4743c00a3bccaec13d07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:48:06 +0100 Subject: [PATCH 083/979] qml: Demo ProgressIndicator control Rebased-From: 7229b0144fbeca070ba10617f133de362c49c3d5 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/pages/stub.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,6 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" +import "../controls" ApplicationWindow { id: appWindow @@ -31,6 +32,14 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ProgressIndicator { + id: indicator + Layout.fillWidth: true + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } + } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 1afc4d87bb9b416c385a0f7286263dd73b2f3928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 3 Nov 2021 17:43:08 +0000 Subject: [PATCH 084/979] ci: Set alias in tasks with artifacts in cirrus.yml Rebased-From: 3bf5e3cf129c3f40dfb15fbc139442d0a180e92e Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 7b8217221a..9c46acb8e5 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -3,8 +3,8 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** To test the recent GUI from the main branch, insecure CI artifacts can be used: -- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/Win64%20\[unit%20tests,%20no%20gui%20tests,%20no%20boost::process,%20no%20functional%20tests\]%20\[focal\]/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macOS%2010.15%20\[gui,%20no%20tests\]%20\[focal\]/insecure_mac_gui.zip) +- for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) +- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. From f6a90dda50b9acad1bdec8ebdb9e661a429c05ee Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 6 Nov 2021 12:09:06 +0200 Subject: [PATCH 085/979] doc: Add a link to Android APK CI artifact to README and PR template Rebased-From: ef99bc9250338360080b85929b3f90f26e8aabd0 Github-Pull: bitcoin-core/gui-qml#87 --- src/qml/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/README.md b/src/qml/README.md index 9c46acb8e5..466066a23f 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -5,6 +5,7 @@ To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. From aeabea2fe3e3c1e93a7f611631eca625e41822e7 Mon Sep 17 00:00:00 2001 From: secondl1ght <85003930+secondl1ght@users.noreply.github.com> Date: Fri, 17 Dec 2021 09:27:09 -0700 Subject: [PATCH 086/979] Add run information to README Rebased-From: 2e3f2a45fad6ecfda62bb4c182141f42184532bf Github-Pull: bitcoin-core/gui-qml#90 --- src/qml/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/README.md b/src/qml/README.md index 466066a23f..040475c353 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -71,3 +71,9 @@ you must configure with the following option: ``` ./configure --with-qml ``` +### Run + +To run the qml GUI: +``` +./src/qt/bitcoin-qt +``` From a5459df1f3289803b0c244e77c9a62bfc5020a8f Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Thu, 23 Dec 2021 09:55:31 -0500 Subject: [PATCH 087/979] doc: standardize headings in qml README Refactor so that there is only one main heading. Rebased-From: 446565de7b68da1ac024554cd718295536c93685 Github-Pull: bitcoin-core/gui-qml#93 --- src/qml/README.md | 10 ++-- src/qml/bitcoin.cpp | 8 ++- src/qml/bitcoin_qml.qrc | 1 - src/qml/components/BlockCounter.qml | 4 +- src/qml/components/ConnectionOptions.qml | 6 +-- src/qml/controls/Header.qml | 69 ------------------------ src/qml/controls/OptionButton.qml | 6 +-- src/qml/controls/ProgressIndicator.qml | 4 +- src/qml/pages/initerrormessage.qml | 4 +- src/qml/pages/stub.qml | 18 ++----- 10 files changed, 23 insertions(+), 107 deletions(-) delete mode 100644 src/qml/controls/Header.qml diff --git a/src/qml/README.md b/src/qml/README.md index 571fd4e42c..b5cac047d8 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -9,7 +9,7 @@ To test the recent GUI from the main branch, insecure CI artifacts can be used: This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. -# Goals and Limitations +## Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. @@ -28,19 +28,19 @@ or improving relevant documentation. Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. -# Development Process +## Development Process This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). -## Minimum Required Qt Version +### Minimum Required Qt Version -All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). +All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.12.11](https://github.com/bitcoin-core/gui-qml/blob/a79a2249d027047f08dffe3f04951d52eac198f1/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. -# Compile and Run +## Compile and Run The master branch is only guaranteed to work and build on Debian-based systems and macOS. Support for more systems will be confirmed and documented as the project matures. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 8216255132..5e035677dd 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -42,12 +42,10 @@ QT_END_NAMESPACE #if defined(QT_STATICPLUGIN) #include -Q_IMPORT_PLUGIN(QtQmlPlugin) -Q_IMPORT_PLUGIN(QtQmlModelsPlugin) -Q_IMPORT_PLUGIN(QtQuick2Plugin) -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); +Q_IMPORT_PLUGIN(QtQuick2Plugin); +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 294768aec6..043d81bba0 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,7 +2,6 @@ components/BlockCounter.qml components/ConnectionOptions.qml - controls/Header.qml controls/OptionButton.qml controls/ProgressIndicator.qml pages/initerrormessage.qml diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..daefc91e52 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 5e0cd6ea5a..f0d315f7b9 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../controls" ColumnLayout { diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml deleted file mode 100644 index 0d065506b2..0000000000 --- a/src/qml/controls/Header.qml +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property bool bold: false - property bool center: true - property string header - property int headerMargin - property int headerSize: 28 - property string description - property int descriptionMargin: 10 - property int descriptionSize: 18 - property string subtext - property int subtextMargin - property int subtextSize: 15 - contentItem: ColumnLayout { - spacing: 0 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - topPadding: root.headerMargin - font.family: "Inter" - font.styleName: root.bold ? "Semi Bold" : "Regular" - font.pointSize: root.headerSize - color: "#FFFFFF" - text: root.header - horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - active: root.description.length > 0 - visible: active - sourceComponent: Label { - topPadding: root.descriptionMargin - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: root.descriptionSize - color: "#DEDEDE" - text: root.description - horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - active: root.subtext.length > 0 - visible: active - sourceComponent: Label { - topPadding: root.subtextMargin - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.subtextSize - color: "#FFFFFF" - text: root.subtext - horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - } - } -} diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 00030dad5f..91281077d3 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..c58f402738 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index 109e51c1a0..e9d4ed8cb0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" import "../controls" @@ -28,18 +28,6 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 0 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 25 - } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From eaf1ea1f34515bb8dc0b51bb7dd2d7c6db398388 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Thu, 23 Dec 2021 10:16:02 -0500 Subject: [PATCH 088/979] doc: qml README wording clarifications - Move the sentence that described what this repo contains to the top. - Improve wording around insecure CI artifacts and there availability. - Improve wording around avoiding conflicts with upstream. - Improve wording around build instructions. Rebased-From: 78dcb133abbfa20e9493699fd53ee64f6ae7f24a Github-Pull: bitcoin-core/gui-qml#93 --- src/qml/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index b5cac047d8..76157c4a24 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,13 +2,13 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -To test the recent GUI from the main branch, insecure CI artifacts can be used: +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - ## Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. @@ -21,12 +21,12 @@ The primary goals of the project can be summed up as follows: - Work alongside the Bitcoin Design community to develop an aesthetic GUI - Develop a mobile-optimized GUI -It is important that we stay as conflict-free as possible with the Bitcoin Core repo. +We must avoid conflicts with the Bitcoin Core repo. As such, this project will aim to make very few changes outside of the qml directory. Pull requests must be focused on developing the GUI itself, adding build support, or improving relevant documentation. -Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. +This project will **not** accept pull requests making any significant changes unrelated to the GUI. ## Development Process @@ -63,14 +63,15 @@ No additional dependencies, besides those in [build-osx.md](../../doc/build-osx. ### Build -For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. +For instructions on how to build and compile Bitcoin Core, refer to your respective system's build doc. -To add support for building the qml GUI, -you must configure with the following option: +As long as the required dependencies are installed, the qml GUI will be built. +To ensure that you are in fact building the qml GUI, you can configure with the following option: ``` ./configure --with-qml ``` + ### Run To run the qml GUI: From 5392de96eb51f774260433c6e792e02d10466481 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Thu, 23 Dec 2021 10:19:59 -0500 Subject: [PATCH 089/979] doc: mention development policies in qml README These are important and need visibility. Rebased-From: b7626b73dab51ab7ace66ee14eed2ee7bb5963c3 Github-Pull: bitcoin-core/gui-qml#93 --- src/qml/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qml/README.md b/src/qml/README.md index 76157c4a24..cc45e416e0 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -40,6 +40,12 @@ All development must adhere to the current upstream Qt Version to minimize our d As the Qt Version changes upstream, refactoring is allowed to use the now available features. +### Policies + +This project has custom policies for development, see: +- [Icon Policy](./doc/icon-policy.md) +- [Translator Comments Policy](./doc/translator-comments.md) + ## Compile and Run The master branch is only guaranteed to work and build on Debian-based systems and macOS. From 01e78ff3381f8c648ec0490f73b30f3ec5555db1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 21 Dec 2021 16:54:32 +0200 Subject: [PATCH 090/979] qml, doc: add Fedora as supported platform This documents the required packages for building on Fedora. Also, make it clear that only Debian requires runtime dependencies. Additionally, some small cleanups to the dependencies section. Rebased-From: 3105e95ed7a50e8017e44cb889526e7fc91c17f8 Github-Pull: bitcoin-core/gui-qml#93 --- src/qml/README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index cc45e416e0..a6f1f7d4d1 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -48,11 +48,15 @@ This project has custom policies for development, see: ## Compile and Run -The master branch is only guaranteed to work and build on Debian-based systems and macOS. +The master branch is only guaranteed to work and build on Debian-based systems, Fedora, and macOS. Support for more systems will be confirmed and documented as the project matures. ### Dependencies -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. + +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), the following additional dependencies are required to compile: + +#### Debian-based systems: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev @@ -65,7 +69,11 @@ they are not needed for static builds: sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. +#### Fedora: + +``` +sudo dnf install qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel +``` ### Build From e857507fb1653cdaf47f3cd78397335850f1cf65 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:12:00 +0200 Subject: [PATCH 091/979] Revert "qml: Demo ProgressIndicator control" This reverts commit b3913d7ca07fb1980112fdd5d0d709ef2aa51e25. Rebased-From: f516100a2e283c8e94c052705f6699321064641d Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 6d94f713fefa44a980ade72d2027b3314f833f54 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:12:08 +0200 Subject: [PATCH 092/979] Revert "doc: Drop unneeded runtime dependencies" This reverts commit 74913c9dbc79da3f83bf40c9e698479e3fb4454e. Rebased-From: 45fc3c5b13ebba8e05b6f407ec92b8af16c51ee8 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 040475c353..4e476fcec5 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -56,7 +56,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. From c4eee3ff985200697f1e22f2edc2f9e2f05730a6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:12:20 +0200 Subject: [PATCH 093/979] Revert "qml: Show ConnectionOptions" This reverts commit c53f257ae091f44284c87872ea3c0514b5580145. Rebased-From: aff0519164b4695e0d1a05cc3d182161eefc017c Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,9 +31,5 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } } } From 7bf8aa37900836da3661390324f2a0c55e12c05b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:12:36 +0200 Subject: [PATCH 094/979] Revert "qml: Use ColumnLayout in application window" This reverts commit f9ecb1ef06bc8e25cc908d72f375014c11859bc0. Rebased-From: 4f8d7635cc3e4c737f2c77b1233b050d2ae2b8eb Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,19 +17,17 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - ColumnLayout { + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + + BlockCounter { + id: blockCounter anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } + blockHeight: nodeModel.blockTipHeight } } From 684df64a087d995c386dcc75f9ae6b2b60cf2dfc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:12:51 +0200 Subject: [PATCH 095/979] Revert "qml: Drop import qualifier BitcoinCoreComponents" This reverts commit cd0326995c179b4fd2d33a4b2a61af020d9f512e. Rebased-From: 671fa9a690d45e74821b6d528aa42b1534005ee7 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,7 +5,8 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow @@ -25,7 +26,7 @@ ApplicationWindow { sourceSize.height: 128 } - BlockCounter { + BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From d23a4ee6969f9b369cb6becb720502df7bbc6659 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 00:13:29 +0200 Subject: [PATCH 096/979] Revert "qml: Set tab focus behavior" This reverts commit 18033643ef077dc74f0bd3c60d55550650951eb2. Rebased-From: 4921665646b0b8358aa81671ef7607276514f5b2 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 5e035677dd..50a9d8f56d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE @@ -96,7 +95,6 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From ad0b4c447c6355f2a0954e229d05bf2c007aef44 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:38:10 +0200 Subject: [PATCH 097/979] Revert "multiprocess: add new bitcoin-qt init implementation to qml-gui" This reverts commit 76fa764f3be85cec7142f0cd67ef929d3f40d71a. Rebased-From: dd5032c4579c4d3fd6493d8f9108d476edb714ef Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 50a9d8f56d..797c8193c7 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -99,12 +100,15 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 6a4038ab989be7071befab962cd8b955e1f3d712 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:38:20 +0200 Subject: [PATCH 098/979] Revert "qml: Drop erroneous `#include `" This reverts commit 6c8b16a3dbf3343bfc8d5f4b1a1acc3ea8b81980. Rebased-From: 19e4520ada84dcd8acd3beffe6e14f10fb24112f Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 797c8193c7..7a64b4f2aa 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE From 6b30e448774d472f66af67562398f9df2a01f502 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:38:34 +0200 Subject: [PATCH 099/979] Revert "qml, build, doc: Allow import QtQuick.Layouts" This reverts commit 37c76df94a4126eb8ceae35f35cc028cf69fbd11. Rebased-From: 3aa2ee9cd1b62c3f91ba53fbce25a5eefc731a74 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 - src/qml/pages/stub.qml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 4e476fcec5..fd31d76c56 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -56,7 +56,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7a64b4f2aa..57e7193ec4 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -46,7 +46,6 @@ QT_END_NAMESPACE Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..7a56f6ce3a 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,7 +4,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From 0836ec568944447feb79669ff0b74258bddfed1a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:38:43 +0200 Subject: [PATCH 100/979] Revert "qml: Add qInstallMessageHandler" This reverts commit e0e4d2ba5929650d516687619c642b49a414fa71. Rebased-From: 0ad30862e12601fd29929a6ec9ec71d82c4e4d82 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 57e7193ec4..6b6adb7c34 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -33,14 +32,9 @@ #include #include #include -#include #include #include -QT_BEGIN_NAMESPACE -class QMessageLogContext; -QT_END_NAMESPACE - #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQuick2Plugin); @@ -72,17 +66,6 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } - -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); - } -} } // namespace @@ -194,9 +177,6 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); - qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); From ec8af00563310d9bc18c9f8b401f818411341178 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:39:10 +0200 Subject: [PATCH 101/979] Revert "build, qml: Add qtquickcontrols2 module" This reverts commit b1b5443701589391d60b530484127302cc7f74c3. Rebased-From: 421da00c1235da7feb057dfbc2ea21bc08e254ea Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 6b6adb7c34..814baa4e2e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -39,8 +39,6 @@ #include Q_IMPORT_PLUGIN(QtQuick2Plugin); Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From 4ac137ea10cf27e8f04f15772e43a6fb5161e8e6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 20 Dec 2021 19:39:19 +0200 Subject: [PATCH 102/979] Revert "build, qml: Add qtdeclarative module" This reverts commit 949c0ca3ec05f49dae45f4811528df64de013b5c. Rebased-From: fdeb39a661571cfff87951deac161244e1797af7 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 814baa4e2e..9bd18f302c 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,12 +35,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQuick2Plugin); -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { From e8e8cc006babb01cdf99757c0d86040239e754ab Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:50:48 +0300 Subject: [PATCH 103/979] build, qml: Add qtdeclarative module QML features are mentioned in the `qt.mk` file explicitly for easy reference. The only exception is the qml-jit feature, the availability of which depends on the host platform. Rebased-From: d3dc7ca762aeef284d1d475b36d3fef84fb1bc46 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9bd18f302c..d41acbf1d5 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,6 +35,14 @@ #include #include +#if defined(QT_STATICPLUGIN) +#include +Q_IMPORT_PLUGIN(QtQmlPlugin) +Q_IMPORT_PLUGIN(QtQmlModelsPlugin) +Q_IMPORT_PLUGIN(QtQuick2Plugin) +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +#endif + namespace { void SetupUIArgs(ArgsManager& argsman) { From 4214f137a2ee9d29011316c1c27535cf542dba13 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:54:11 +0300 Subject: [PATCH 104/979] build, qml: Add qtquickcontrols2 module Rebased-From: 9a1f9249ad864fe0a627b70546d773144d71f907 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index d41acbf1d5..508f7bad75 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,6 +41,8 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From 2890eb81c89fb61fa3426e2eaa1c3c68bcdd9adf Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:13:33 +0300 Subject: [PATCH 105/979] qml: Add qInstallMessageHandler Rebased-From: 96dd04db08cfb55429b2d82bbec02af17bfcda8a Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 508f7bad75..afcf9408c6 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,14 @@ #include #include #include +#include #include #include +QT_BEGIN_NAMESPACE +class QMessageLogContext; +QT_END_NAMESPACE + #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQmlPlugin) @@ -68,6 +74,17 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } + +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } +} } // namespace @@ -179,6 +196,9 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + // Install qDebug() message handler to route to debug.log + qInstallMessageHandler(DebugMessageHandler); + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); return qGuiApp->exec(); From cdb8b5ce2c7196cb52a4322510d2900e7a2f146b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 3 Oct 2021 14:32:13 +0300 Subject: [PATCH 106/979] qml, doc: Add import QtQuick.Layouts Rebased-From: 56c2ae3c60daee4dbd6217db14f3b979e4698409 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 + src/qml/pages/stub.qml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index fd31d76c56..4e476fcec5 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -56,7 +56,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index afcf9408c6..2f159cd235 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -47,6 +47,7 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 7a56f6ce3a..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,6 +4,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From ef486add83715ec857adf5635b6908aca1d916ff Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:33:02 +0300 Subject: [PATCH 107/979] qml: Drop erroneous `#include ` To use the `QStringLiteral` macro, the `QString` header should be included, that is done already. Rebased-From: 08cb175cd9742e20c4006551b35931fb373b3822 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 2f159cd235..247e20c874 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE From 23d0d84861cfe227a51807d67b019edc26915ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:20:03 +0100 Subject: [PATCH 108/979] qml: Set tab focus behavior Rebased-From: 93799b1019804ce6e2427e0b31f31d7fa3c9f513 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 247e20c874..632e59054e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -98,6 +99,7 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 245b891017adc92af9af2e59f57137f469699e06 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 27 Oct 2021 14:49:32 -0400 Subject: [PATCH 109/979] multiprocess: add new bitcoin-qt init implementation to qml-gui This incorporates the new bitcoin-qt init implementation into the qml-gui. Rebased-From: 97e36b1479a8891f9545cd40bc7cf7c748a72cee Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/bitcoin.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 632e59054e..8216255132 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -104,15 +103,12 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 9c72e91cdd2582029782d00cff7551e6c4c48a88 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:17:44 +0300 Subject: [PATCH 110/979] doc: Drop unneeded runtime dependencies Rebased-From: 5163f9483d3919200ce7e713543573d1650cc7aa Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 4e476fcec5..040475c353 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -56,7 +56,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. From a54216909cc1858be8c87b4022b714a6d806b867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:10:14 +0100 Subject: [PATCH 111/979] qml: Drop import qualifier BitcoinCoreComponents Rebased-From: 7ede84d53c52df21a714468f9c09032efa63ce80 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,8 +5,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" as BitcoinCoreComponents - +import "../components" ApplicationWindow { id: appWindow @@ -26,7 +25,7 @@ ApplicationWindow { sourceSize.height: 128 } - BitcoinCoreComponents.BlockCounter { + BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From 0cb0f41f01700611f72b2b53950a68c24d0b237f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:44:47 +0100 Subject: [PATCH 112/979] qml: Use ColumnLayout in application window Rebased-From: 6aa6d095a030d3634875851b2da8ffa8c6788ef9 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,17 +17,19 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - Image { - id: appLogo - anchors.horizontalCenter: parent.horizontalCenter - source: "image://images/app" - sourceSize.width: 128 - sourceSize.height: 128 - } - - BlockCounter { - id: blockCounter + ColumnLayout { anchors.centerIn: parent - blockHeight: nodeModel.blockTipHeight + spacing: 15 + width: 400 + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } } } From c304bd08b3e17f08bee0028a74e8f7e0f6e7f9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:46:48 +0100 Subject: [PATCH 113/979] qml: Show ConnectionOptions Rebased-From: 37e0569650f77252369ae68cc8857234ad8ed52c Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,5 +31,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ConnectionOptions { + Layout.preferredWidth: 400 + focus: true + } } } From dc71991594316192f98cf8395e71d11476ada582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:48:06 +0100 Subject: [PATCH 114/979] qml: Demo ProgressIndicator control Rebased-From: 3bfb4ac7533af0dff3acab8afd7646a25bef6fe8 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/pages/stub.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,6 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" +import "../controls" ApplicationWindow { id: appWindow @@ -31,6 +32,14 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ProgressIndicator { + id: indicator + Layout.fillWidth: true + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } + } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 47a33cb48e76678a589c34cbe9f979d6cdc9b164 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 24 Dec 2021 12:04:23 +0200 Subject: [PATCH 115/979] scripted-diff: Bump Qt Quick module versions -BEGIN VERIFY SCRIPT- QML_FILES=$(git ls-files '*.qml') sed -i -e 's/import QtQuick 2.12/import QtQuick 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Controls 2.12/import QtQuick.Controls 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Layouts 1.11/import QtQuick.Layouts 1.15/' -- $QML_FILES -END VERIFY SCRIPT- Rebased-From: e311e7289fb64fac7c1ceeda2924e120bfa72734 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/components/BlockCounter.qml | 4 ++-- src/qml/components/ConnectionOptions.qml | 6 +++--- src/qml/controls/OptionButton.qml | 6 +++--- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/pages/initerrormessage.qml | 4 ++-- src/qml/pages/stub.qml | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index daefc91e52..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index f0d315f7b9..5e0cd6ea5a 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import "../controls" ColumnLayout { diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 91281077d3..00030dad5f 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index c58f402738..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index e9d4ed8cb0..109e51c1a0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..a3f36376d9 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import "../components" import "../controls" From c7685a56527d5781fdef6aa3b9c7d98078f5dcb2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 24 Dec 2021 12:06:22 +0200 Subject: [PATCH 116/979] qml, doc: Update minimum required Qt version Rebased-From: 9670935449e0b6797e93029e29e1aae157ec23d2 Github-Pull: bitcoin-core/gui-qml#91 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 040475c353..571fd4e42c 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -36,7 +36,7 @@ Contributions are welcome from all, developers and designers. If you are a new c ## Minimum Required Qt Version -All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.12.11](https://github.com/bitcoin-core/gui-qml/blob/a79a2249d027047f08dffe3f04951d52eac198f1/depends/packages/qt.mk#L2). +All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. From 819cd61c91e1eccfece9b0d071836e665f7128f0 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Sun, 2 Jan 2022 22:58:39 -0500 Subject: [PATCH 117/979] qml: introduce Header qml control Rebased-From: 11bc38fde20aa826e4509228ffc22f6a49028ea3 Github-Pull: bitcoin-core/gui-qml#100 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/Header.qml | 69 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/qml/controls/Header.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 043d81bba0..294768aec6 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,6 +2,7 @@ components/BlockCounter.qml components/ConnectionOptions.qml + controls/Header.qml controls/OptionButton.qml controls/ProgressIndicator.qml pages/initerrormessage.qml diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml new file mode 100644 index 0000000000..0d065506b2 --- /dev/null +++ b/src/qml/controls/Header.qml @@ -0,0 +1,69 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + property bool bold: false + property bool center: true + property string header + property int headerMargin + property int headerSize: 28 + property string description + property int descriptionMargin: 10 + property int descriptionSize: 18 + property string subtext + property int subtextMargin + property int subtextSize: 15 + contentItem: ColumnLayout { + spacing: 0 + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + topPadding: root.headerMargin + font.family: "Inter" + font.styleName: root.bold ? "Semi Bold" : "Regular" + font.pointSize: root.headerSize + color: "#FFFFFF" + text: root.header + horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft + wrapMode: Text.WordWrap + } + Loader { + Layout.fillWidth: true + Layout.preferredWidth: 0 + active: root.description.length > 0 + visible: active + sourceComponent: Label { + topPadding: root.descriptionMargin + font.family: "Inter" + font.styleName: "Regular" + font.pointSize: root.descriptionSize + color: "#DEDEDE" + text: root.description + horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft + wrapMode: Text.WordWrap + } + } + Loader { + Layout.fillWidth: true + Layout.preferredWidth: 0 + active: root.subtext.length > 0 + visible: active + sourceComponent: Label { + topPadding: root.subtextMargin + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: root.subtextSize + color: "#FFFFFF" + text: root.subtext + horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft + wrapMode: Text.WordWrap + } + } + } +} From a6ad799adebf55ed0c67c659dbfc878108f76a5d Mon Sep 17 00:00:00 2001 From: jarolrod Date: Sun, 2 Jan 2022 22:59:24 -0500 Subject: [PATCH 118/979] qml: demo Header control Rebased-From: 6aee4e3042b669c17bf03e57fad6da900e4b260c Github-Pull: bitcoin-core/gui-qml#100 --- src/qml/pages/stub.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a3f36376d9..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -28,6 +28,18 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 0 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 25 + } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From 308f308d74a9fe4e648129297dd3f5937e0eac21 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 3 Jan 2022 16:00:29 -0500 Subject: [PATCH 119/979] qml: introduce ContinueButton control Rebased-From: d0388988b5467775017a2be187c199fee9e5563e Github-Pull: bitcoin-core/gui-qml#101 --- src/qml/README.md | 45 +++++-------- src/qml/bitcoin.cpp | 2 +- src/qml/bitcoin_qml.qrc | 1 + src/qml/components/ConnectionOptions.qml | 8 --- src/qml/controls/ContinueButton.qml | 25 ++++++++ src/qml/controls/Header.qml | 2 +- src/qml/controls/OptionButton.qml | 82 +++++++++++------------- src/qml/nodemodel.cpp | 36 ++--------- src/qml/nodemodel.h | 18 +----- src/qml/pages/stub.qml | 5 +- 10 files changed, 89 insertions(+), 135 deletions(-) create mode 100644 src/qml/controls/ContinueButton.qml diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..571fd4e42c 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,14 +2,14 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - -Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: +To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) -## Goals and Limitations +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +# Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. @@ -21,42 +21,32 @@ The primary goals of the project can be summed up as follows: - Work alongside the Bitcoin Design community to develop an aesthetic GUI - Develop a mobile-optimized GUI -We must avoid conflicts with the Bitcoin Core repo. +It is important that we stay as conflict-free as possible with the Bitcoin Core repo. As such, this project will aim to make very few changes outside of the qml directory. Pull requests must be focused on developing the GUI itself, adding build support, or improving relevant documentation. -This project will **not** accept pull requests making any significant changes unrelated to the GUI. +Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. -## Development Process +# Development Process This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). -### Minimum Required Qt Version +## Minimum Required Qt Version All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. -### Policies +# Compile and Run -This project has custom policies for development, see: -- [Icon Policy](./doc/icon-policy.md) -- [Translator Comments Policy](./doc/translator-comments.md) - -## Compile and Run - -The master branch is only guaranteed to work and build on Debian-based systems, Fedora, and macOS. +The master branch is only guaranteed to work and build on Debian-based systems and macOS. Support for more systems will be confirmed and documented as the project matures. ### Dependencies -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. - -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), the following additional dependencies are required to compile: - -#### Debian-based systems: +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev @@ -69,23 +59,18 @@ they are not needed for static builds: sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` -#### Fedora: - -``` -sudo dnf install qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel -``` +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. ### Build -For instructions on how to build and compile Bitcoin Core, refer to your respective system's build doc. +For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. -As long as the required dependencies are installed, the qml GUI will be built. -To ensure that you are in fact building the qml GUI, you can configure with the following option: +To add support for building the qml GUI, +you must configure with the following option: ``` ./configure --with-qml ``` - ### Run To run the qml GUI: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4cea873af2..8216255132 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -170,6 +170,7 @@ int QmlGuiMain(int argc, char* argv[]) qGuiApp->setQuitOnLastWindowClosed(false); QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] { node->startShutdown(); + node_model.startNodeShutdown(); }); GUIUtil::LoadFont(":/fonts/inter/regular"); @@ -198,6 +199,5 @@ int QmlGuiMain(int argc, char* argv[]) qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); - node_model.startShutdownPolling(); return qGuiApp->exec(); } diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 294768aec6..27c2d15f74 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,6 +2,7 @@ components/BlockCounter.qml components/ConnectionOptions.qml + controls/ContinueButton.qml controls/Header.qml controls/OptionButton.qml controls/ProgressIndicator.qml diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 21a3d3079d..5e0cd6ea5a 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -31,13 +31,5 @@ ColumnLayout { Layout.fillWidth: true text: qsTr("Only when on Wi-Fi") description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") - detail: ProgressIndicator { - implicitWidth: 50 - SequentialAnimation on progress { - loops: Animation.Infinite - SmoothedAnimation { to: 1; velocity: 1; } - SmoothedAnimation { to: 0; velocity: 1; } - } - } } } diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml new file mode 100644 index 0000000000..9f42e92bdf --- /dev/null +++ b/src/qml/controls/ContinueButton.qml @@ -0,0 +1,25 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Button { + font.family: "Inter" + font.styleName: "Semi Bold" + font.pointSize: 18 + contentItem: Text { + text: parent.text + font: parent.font + color: "white" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + background: Rectangle { + implicitHeight: 46 + implicitWidth: 300 + color: "#F7931A" + radius: 5 + } +} diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 20dc80b3ac..0d065506b2 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -10,7 +10,7 @@ Control { id: root property bool bold: false property bool center: true - required property string header + property string header property int headerMargin property int headerSize: 28 property string description diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 0211a8fa7a..00030dad5f 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -12,7 +12,6 @@ Button { id: button padding: 15 checkable: true - property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" @@ -29,53 +28,46 @@ Button { opacity: 0.4 } } - contentItem: RowLayout { + contentItem: ColumnLayout { spacing: 3 - ColumnLayout { - spacing: 3 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: 18 - color: "white" - text: button.text - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 15 - color: "#DEDEDE" - text: button.description - wrapMode: Text.WordWrap - } - Loader { - Layout.topMargin: 2 - active: button.recommended - visible: active - sourceComponent: Label { - background: Rectangle { - color: "white" - radius: 3 - } - font.styleName: "Regular" - font.pixelSize: 13 - topPadding: 3 - rightPadding: 7 - bottomPadding: 4 - leftPadding: 7 - color: "black" - text: qsTr("Recommended") - } - } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pointSize: 18 + color: "white" + text: button.text + wrapMode: Text.WordWrap + } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: 15 + color: "#DEDEDE" + text: button.description + wrapMode: Text.WordWrap } Loader { - id: detail_loader - visible: item + Layout.topMargin: 2 + active: button.recommended + visible: active + sourceComponent: Label { + background: Rectangle { + color: "white" + radius: 3 + } + font.styleName: "Regular" + font.pixelSize: 13 + topPadding: 3 + rightPadding: 7 + bottomPadding: 4 + leftPadding: 7 + color: "black" + text: qsTr("Recommended") + } } } } diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 6643d43a99..45601791df 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -8,9 +8,6 @@ #include #include -#include - -#include NodeModel::NodeModel(interfaces::Node& node) : m_node{node} @@ -26,52 +23,27 @@ void NodeModel::setBlockTipHeight(int new_height) } } -void NodeModel::setVerificationProgress(double new_progress) +void NodeModel::startNodeInitializionThread() { - if (new_progress != m_verification_progress) { - m_verification_progress = new_progress; - Q_EMIT verificationProgressChanged(); - } + Q_EMIT requestedInitialize(); } -void NodeModel::startNodeInitializionThread() +void NodeModel::startNodeShutdown() { - Q_EMIT requestedInitialize(); + Q_EMIT requestedShutdown(); } void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::BlockAndHeaderTipInfo tip_info) { // TODO: Handle the `success` parameter, setBlockTipHeight(tip_info.block_height); - setVerificationProgress(tip_info.verification_progress); -} - -void NodeModel::startShutdownPolling() -{ - m_shutdown_polling_timer_id = startTimer(200ms); -} - -void NodeModel::stopShutdownPolling() -{ - killTimer(m_shutdown_polling_timer_id); -} - -void NodeModel::timerEvent(QTimerEvent* event) -{ - Q_UNUSED(event) - if (m_node.shutdownRequested()) { - stopShutdownPolling(); - Q_EMIT requestedShutdown(); - } } void NodeModel::ConnectToBlockTipSignal() { assert(!m_handler_notify_block_tip); - m_handler_notify_block_tip = m_node.handleNotifyBlockTip( [this](SynchronizationState state, interfaces::BlockTip tip, double verification_progress) { setBlockTipHeight(tip.block_height); - setVerificationProgress(verification_progress); }); } diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index c6a04a1f2c..b3190a0199 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -12,10 +12,6 @@ #include -QT_BEGIN_NAMESPACE -class QTimerEvent; -QT_END_NAMESPACE - namespace interfaces { class Node; } @@ -25,20 +21,15 @@ class NodeModel : public QObject { Q_OBJECT Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) - Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged) public: explicit NodeModel(interfaces::Node& node); int blockTipHeight() const { return m_block_tip_height; } void setBlockTipHeight(int new_height); - double verificationProgress() const { return m_verification_progress; } - void setVerificationProgress(double new_progress); Q_INVOKABLE void startNodeInitializionThread(); - - void startShutdownPolling(); - void stopShutdownPolling(); + void startNodeShutdown(); public Q_SLOTS: void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info); @@ -47,17 +38,10 @@ public Q_SLOTS: void blockTipHeightChanged(); void requestedInitialize(); void requestedShutdown(); - void verificationProgressChanged(); - -protected: - void timerEvent(QTimerEvent* event) override; private: // Properties that are exposed to QML. int m_block_tip_height{0}; - double m_verification_progress{0.0}; - - int m_shutdown_polling_timer_id{0}; interfaces::Node& m_node; std::unique_ptr m_handler_notify_block_tip; diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,7 +47,10 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: nodeModel.verificationProgress + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } } ConnectionOptions { Layout.preferredWidth: 400 From 99e3638c0335233ce13a63939268a186a756f96d Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 3 Jan 2022 16:12:05 -0500 Subject: [PATCH 120/979] qml: introduce OptionSwitch control Rebased-From: f41fb209a810b24973d2db93a1aa03936b93d721 Github-Pull: bitcoin-core/gui-qml#101 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/OptionSwitch.qml | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/qml/controls/OptionSwitch.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 27c2d15f74..fd345e7727 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -5,6 +5,7 @@ controls/ContinueButton.qml controls/Header.qml controls/OptionButton.qml + controls/OptionSwitch.qml controls/ProgressIndicator.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml new file mode 100644 index 0000000000..947870a85d --- /dev/null +++ b/src/qml/controls/OptionSwitch.qml @@ -0,0 +1,27 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Switch { + id: root + indicator: Rectangle { + implicitWidth: 45 + implicitHeight: 28 + x: root.leftPadding + y: parent.height / 2 - height / 2 + radius: 18 + color: root.checked ? "#F7931A" : "#DDDDDD" + Rectangle { + id: indicatorButton + y: parent.height / 2 - height / 2 + x: root.checked ? parent.width - width - 4 : 0 + 4 + width: 20 + height: 20 + radius: 18 + color: "#ffffff" + } + } +} From 93375383e2759d701962bbc3c984de267cfb0240 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 3 Jan 2022 16:19:21 -0500 Subject: [PATCH 121/979] qml: introduce Setting control Rebased-From: d7eea9362421b3c896207e04a87d1d0eff92b928 Github-Pull: bitcoin-core/gui-qml#101 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/Setting.qml | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/qml/controls/Setting.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index fd345e7727..56a2b3962c 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -7,6 +7,7 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml + controls/Setting.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml new file mode 100644 index 0000000000..c636aa96c9 --- /dev/null +++ b/src/qml/controls/Setting.qml @@ -0,0 +1,41 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + property bool last: false + property string header + property string description + contentItem: GridLayout { + columns: 2 + rowSpacing: 20 + width: parent.width + Header { + Layout.fillWidth: true + center: false + header: root.header + headerSize: 18 + description: root.description + descriptionSize: 15 + descriptionMargin: 0 + } + OptionSwitch { + Layout.alignment: Qt.AlignRight + } + Loader { + Layout.fillWidth:true + Layout.columnSpan: 2 + active: !last + visible: active + sourceComponent: Rectangle { + height: 1 + color: "#777777" + } + } + } +} From 92d8a7ac4a05b1fc668ce346a42fb774807a4ef1 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 3 Jan 2022 16:24:45 -0500 Subject: [PATCH 122/979] qml: introduce ConnectionSettings component Rebased-From: c026a3e85c8e21519c85b840a4ee8e8d444eb88d Github-Pull: bitcoin-core/gui-qml#101 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/components/ConnectionSettings.qml | 35 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/qml/components/ConnectionSettings.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 56a2b3962c..4c12fec837 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,6 +2,7 @@ components/BlockCounter.qml components/ConnectionOptions.qml + components/ConnectionSettings.qml controls/ContinueButton.qml controls/Header.qml controls/OptionButton.qml diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml new file mode 100644 index 0000000000..5db05b5933 --- /dev/null +++ b/src/qml/components/ConnectionSettings.qml @@ -0,0 +1,35 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + spacing: 20 + Setting { + Layout.fillWidth: true + header: "Use cellular data" + } + Setting { + Layout.fillWidth: true + header: "Daily upload limit" + } + Setting { + Layout.fillWidth: true + header: "Connection limit" + } + Setting { + Layout.fillWidth: true + header: "Listening enabled" + description: "Reduces data usage." + } + Setting { + last: true + Layout.fillWidth: true + header: "Blocks Only" + description: "Do not transfer unconfirmed transactions. Also disabled listening." + } +} From dde6e74a89529266392d730ec1aedcb6f07d72e3 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 5 Jan 2022 18:09:43 -0500 Subject: [PATCH 123/979] qml: make header property required in header control This makes qt enforce that the header property is required to use the header control. If no value is provided to the header property, the gui will not start. Rebased-From: 43aaa990370622d1129e3fd66648b831a58b720b Github-Pull: bitcoin-core/gui-qml#107 --- src/qml/README.md | 45 +++++++++++++------------------------ src/qml/controls/Header.qml | 2 +- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..571fd4e42c 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,14 +2,14 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - -Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: +To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) -## Goals and Limitations +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +# Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. @@ -21,42 +21,32 @@ The primary goals of the project can be summed up as follows: - Work alongside the Bitcoin Design community to develop an aesthetic GUI - Develop a mobile-optimized GUI -We must avoid conflicts with the Bitcoin Core repo. +It is important that we stay as conflict-free as possible with the Bitcoin Core repo. As such, this project will aim to make very few changes outside of the qml directory. Pull requests must be focused on developing the GUI itself, adding build support, or improving relevant documentation. -This project will **not** accept pull requests making any significant changes unrelated to the GUI. +Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. -## Development Process +# Development Process This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). -### Minimum Required Qt Version +## Minimum Required Qt Version All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. -### Policies +# Compile and Run -This project has custom policies for development, see: -- [Icon Policy](./doc/icon-policy.md) -- [Translator Comments Policy](./doc/translator-comments.md) - -## Compile and Run - -The master branch is only guaranteed to work and build on Debian-based systems, Fedora, and macOS. +The master branch is only guaranteed to work and build on Debian-based systems and macOS. Support for more systems will be confirmed and documented as the project matures. ### Dependencies -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. - -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), the following additional dependencies are required to compile: - -#### Debian-based systems: +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev @@ -69,23 +59,18 @@ they are not needed for static builds: sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` -#### Fedora: - -``` -sudo dnf install qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel -``` +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. ### Build -For instructions on how to build and compile Bitcoin Core, refer to your respective system's build doc. +For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. -As long as the required dependencies are installed, the qml GUI will be built. -To ensure that you are in fact building the qml GUI, you can configure with the following option: +To add support for building the qml GUI, +you must configure with the following option: ``` ./configure --with-qml ``` - ### Run To run the qml GUI: diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 0d065506b2..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -10,7 +10,7 @@ Control { id: root property bool bold: false property bool center: true - property string header + required property string header property int headerMargin property int headerSize: 28 property string description From e7f43007308810083f6e6e9ace10554302d1226f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 5 Jan 2022 01:05:13 +0000 Subject: [PATCH 124/979] qml: Support detail item inside OptionButton Rebased-From: ab460a561cef8f557d0862b45dcc7134d5259518 Github-Pull: bitcoin-core/gui-qml#103 --- src/qml/README.md | 45 ++++++----------- src/qml/controls/Header.qml | 2 +- src/qml/controls/OptionButton.qml | 82 +++++++++++++++++-------------- 3 files changed, 61 insertions(+), 68 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..571fd4e42c 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,14 +2,14 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - -Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: +To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) -## Goals and Limitations +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +# Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. @@ -21,42 +21,32 @@ The primary goals of the project can be summed up as follows: - Work alongside the Bitcoin Design community to develop an aesthetic GUI - Develop a mobile-optimized GUI -We must avoid conflicts with the Bitcoin Core repo. +It is important that we stay as conflict-free as possible with the Bitcoin Core repo. As such, this project will aim to make very few changes outside of the qml directory. Pull requests must be focused on developing the GUI itself, adding build support, or improving relevant documentation. -This project will **not** accept pull requests making any significant changes unrelated to the GUI. +Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. -## Development Process +# Development Process This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). -### Minimum Required Qt Version +## Minimum Required Qt Version All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. -### Policies +# Compile and Run -This project has custom policies for development, see: -- [Icon Policy](./doc/icon-policy.md) -- [Translator Comments Policy](./doc/translator-comments.md) - -## Compile and Run - -The master branch is only guaranteed to work and build on Debian-based systems, Fedora, and macOS. +The master branch is only guaranteed to work and build on Debian-based systems and macOS. Support for more systems will be confirmed and documented as the project matures. ### Dependencies -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. - -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), the following additional dependencies are required to compile: - -#### Debian-based systems: +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev @@ -69,23 +59,18 @@ they are not needed for static builds: sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` -#### Fedora: - -``` -sudo dnf install qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel -``` +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. ### Build -For instructions on how to build and compile Bitcoin Core, refer to your respective system's build doc. +For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. -As long as the required dependencies are installed, the qml GUI will be built. -To ensure that you are in fact building the qml GUI, you can configure with the following option: +To add support for building the qml GUI, +you must configure with the following option: ``` ./configure --with-qml ``` - ### Run To run the qml GUI: diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 20dc80b3ac..0d065506b2 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -10,7 +10,7 @@ Control { id: root property bool bold: false property bool center: true - required property string header + property string header property int headerMargin property int headerSize: 28 property string description diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 00030dad5f..0211a8fa7a 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -12,6 +12,7 @@ Button { id: button padding: 15 checkable: true + property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" @@ -28,46 +29,53 @@ Button { opacity: 0.4 } } - contentItem: ColumnLayout { + contentItem: RowLayout { spacing: 3 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: 18 - color: "white" - text: button.text - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 15 - color: "#DEDEDE" - text: button.description - wrapMode: Text.WordWrap - } - Loader { - Layout.topMargin: 2 - active: button.recommended - visible: active - sourceComponent: Label { - background: Rectangle { - color: "white" - radius: 3 - } + ColumnLayout { + spacing: 3 + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pointSize: 18 + color: "white" + text: button.text + wrapMode: Text.WordWrap + } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" font.styleName: "Regular" - font.pixelSize: 13 - topPadding: 3 - rightPadding: 7 - bottomPadding: 4 - leftPadding: 7 - color: "black" - text: qsTr("Recommended") + font.pixelSize: 15 + color: "#DEDEDE" + text: button.description + wrapMode: Text.WordWrap + } + Loader { + Layout.topMargin: 2 + active: button.recommended + visible: active + sourceComponent: Label { + background: Rectangle { + color: "white" + radius: 3 + } + font.styleName: "Regular" + font.pixelSize: 13 + topPadding: 3 + rightPadding: 7 + bottomPadding: 4 + leftPadding: 7 + color: "black" + text: qsTr("Recommended") + } } } + Loader { + id: detail_loader + visible: item + } } } From bc91c6a4a155b48f18ab07dfd251fc41ebf4f83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 5 Jan 2022 01:06:33 +0000 Subject: [PATCH 125/979] qml: Demo OptionButton detail in wifi-only option Rebased-From: a55553c560b80e8cc8409937e3ba9c97d4ee5f85 Github-Pull: bitcoin-core/gui-qml#103 --- src/qml/components/ConnectionOptions.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 5e0cd6ea5a..21a3d3079d 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -31,5 +31,13 @@ ColumnLayout { Layout.fillWidth: true text: qsTr("Only when on Wi-Fi") description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") + detail: ProgressIndicator { + implicitWidth: 50 + SequentialAnimation on progress { + loops: Animation.Infinite + SmoothedAnimation { to: 1; velocity: 1; } + SmoothedAnimation { to: 0; velocity: 1; } + } + } } } From 94d94bfd6ee9fd1ee683a308451304335ac66601 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:14:26 +0200 Subject: [PATCH 126/979] qml: Add shutdown polling facilities to the NodeModel class Rebased-From: b6c01bbd55803710a5be469a5b06ac631cedcb66 Github-Pull: bitcoin-core/gui-qml#108 --- src/qml/nodemodel.cpp | 33 ++++++++++++++++++++++----------- src/qml/nodemodel.h | 17 ++++++++++++----- src/qml/pages/stub.qml | 5 ++++- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index b599eba066..27ef2656f3 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -8,6 +8,9 @@ #include #include +#include + +#include NodeModel::NodeModel(interfaces::Node& node) : m_node{node} @@ -23,14 +26,6 @@ void NodeModel::setBlockTipHeight(int new_height) } } -void NodeModel::setVerificationProgress(double new_progress) -{ - if (new_progress != m_verification_progress) { - m_verification_progress = new_progress; - Q_EMIT verificationProgressChanged(); - } -} - void NodeModel::startNodeInitializionThread() { Q_EMIT requestedInitialize(); @@ -45,16 +40,32 @@ void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::Bloc { // TODO: Handle the `success` parameter, setBlockTipHeight(tip_info.block_height); - setVerificationProgress(tip_info.verification_progress); +} + +void NodeModel::startShutdownPolling() +{ + m_shutdown_polling_timer_id = startTimer(200ms); +} + +void NodeModel::stopShutdownPolling() +{ + killTimer(m_shutdown_polling_timer_id); +} + +void NodeModel::timerEvent(QTimerEvent* event) +{ + Q_UNUSED(event) + if (m_node.shutdownRequested()) { + stopShutdownPolling(); + Q_EMIT requestedShutdown(); + } } void NodeModel::ConnectToBlockTipSignal() { assert(!m_handler_notify_block_tip); - m_handler_notify_block_tip = m_node.handleNotifyBlockTip( [this](SynchronizationState state, interfaces::BlockTip tip, double verification_progress) { setBlockTipHeight(tip.block_height); - setVerificationProgress(verification_progress); }); } diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index bc9f4a9f1a..b170ffce10 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -12,6 +12,10 @@ #include +QT_BEGIN_NAMESPACE +class QTimerEvent; +QT_END_NAMESPACE + namespace interfaces { class Node; } @@ -21,19 +25,19 @@ class NodeModel : public QObject { Q_OBJECT Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) - Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged) public: explicit NodeModel(interfaces::Node& node); int blockTipHeight() const { return m_block_tip_height; } void setBlockTipHeight(int new_height); - double verificationProgress() const { return m_verification_progress; } - void setVerificationProgress(double new_progress); Q_INVOKABLE void startNodeInitializionThread(); void startNodeShutdown(); + void startShutdownPolling(); + void stopShutdownPolling(); + public Q_SLOTS: void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info); @@ -41,12 +45,15 @@ public Q_SLOTS: void blockTipHeightChanged(); void requestedInitialize(); void requestedShutdown(); - void verificationProgressChanged(); + +protected: + void timerEvent(QTimerEvent* event) override; private: // Properties that are exposed to QML. int m_block_tip_height{0}; - double m_verification_progress{0.0}; + + int m_shutdown_polling_timer_id{0}; interfaces::Node& m_node; std::unique_ptr m_handler_notify_block_tip; diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,7 +47,10 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: nodeModel.verificationProgress + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } } ConnectionOptions { Layout.preferredWidth: 400 From a7385fec04af377f09d1ba0e0f4bf7a7f4cbf660 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:21:33 +0200 Subject: [PATCH 127/979] qml: Use NodeModel's shutdown polling facilities This change allows to quit the GUI from the command line. Rebased-From: 3c821a05d33f434d980b80c9e0b55ff97d3db976 Github-Pull: bitcoin-core/gui-qml#108 --- src/qml/bitcoin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 8216255132..4cea873af2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -170,7 +170,6 @@ int QmlGuiMain(int argc, char* argv[]) qGuiApp->setQuitOnLastWindowClosed(false); QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] { node->startShutdown(); - node_model.startNodeShutdown(); }); GUIUtil::LoadFont(":/fonts/inter/regular"); @@ -199,5 +198,6 @@ int QmlGuiMain(int argc, char* argv[]) qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); + node_model.startShutdownPolling(); return qGuiApp->exec(); } From a78cc21ba58fd03652d3f9594fb2a3d0fe97ecd0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:21:59 +0200 Subject: [PATCH 128/979] qml: Drop no longer used NodeModel::startNodeShutdown() Rebased-From: ea7f523bd62d409d1f9e5c3d65c6a39a0f8f79a4 Github-Pull: bitcoin-core/gui-qml#108 --- src/qml/nodemodel.cpp | 5 ----- src/qml/nodemodel.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 27ef2656f3..0d7569b69b 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -31,11 +31,6 @@ void NodeModel::startNodeInitializionThread() Q_EMIT requestedInitialize(); } -void NodeModel::startNodeShutdown() -{ - Q_EMIT requestedShutdown(); -} - void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::BlockAndHeaderTipInfo tip_info) { // TODO: Handle the `success` parameter, diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index b170ffce10..580789db25 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -33,7 +33,6 @@ class NodeModel : public QObject void setBlockTipHeight(int new_height); Q_INVOKABLE void startNodeInitializionThread(); - void startNodeShutdown(); void startShutdownPolling(); void stopShutdownPolling(); From 1ade157dcab88bb1743f55fdb00a633349c9a935 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 6 Jan 2022 19:54:07 +0530 Subject: [PATCH 129/979] qml: Add m_verification_progress to display working progress bar - This commit adds a new private member to nodemodel.cpp which allows displaying working progress bar. - Added appropriate getter and setter for this new member variable. - Used this variable appropriately so that its value will update each time a new block is scanned. Rebased-From: 3ea9dfc80d380efb7dd76d2c8159d9328029e759 Github-Pull: bitcoin-core/gui-qml#99 --- src/qml/README.md | 47 +++++-------- src/qml/bitcoin.cpp | 8 +-- src/qml/bitcoin_qml.qrc | 1 - src/qml/components/BlockCounter.qml | 4 +- src/qml/components/ConnectionOptions.qml | 14 +--- src/qml/controls/Header.qml | 69 ------------------- src/qml/controls/OptionButton.qml | 88 +++++++++++------------- src/qml/controls/ProgressIndicator.qml | 4 +- src/qml/nodemodel.cpp | 11 +++ src/qml/nodemodel.h | 5 ++ src/qml/pages/initerrormessage.qml | 4 +- src/qml/pages/stub.qml | 18 +---- 12 files changed, 87 insertions(+), 186 deletions(-) delete mode 100644 src/qml/controls/Header.qml diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..040475c353 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -2,14 +2,14 @@ **WARNING: THIS IS EXPERIMENTAL, DO NOT USE BUILDS FROM THIS REPO FOR REAL TRANSACTIONS!** -This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. - -Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: +To test the recent GUI from the main branch, insecure CI artifacts can be used: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) -## Goals and Limitations +This directory contains the source code for an experimental Bitcoin Core graphical user interface (GUI) built using the [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) framework. + +# Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. This project will start from a clean slate to produce a feature-rich GUI with intuitive user flows and first-class design. @@ -21,42 +21,32 @@ The primary goals of the project can be summed up as follows: - Work alongside the Bitcoin Design community to develop an aesthetic GUI - Develop a mobile-optimized GUI -We must avoid conflicts with the Bitcoin Core repo. +It is important that we stay as conflict-free as possible with the Bitcoin Core repo. As such, this project will aim to make very few changes outside of the qml directory. Pull requests must be focused on developing the GUI itself, adding build support, or improving relevant documentation. -This project will **not** accept pull requests making any significant changes unrelated to the GUI. +Note that this project will **not** accept pull requests making any significant changes unrelated to the GUI. -## Development Process +# Development Process This repo is synced with the [Bitcoin Core repo](https://github.com/bitcoin/bitcoin) on a weekly basis, or as needed to resolve conflicts. Contributions are welcome from all, developers and designers. If you are a new contributor, please read [CONTRIBUTING.md](../../CONTRIBUTING.md). -### Minimum Required Qt Version +## Minimum Required Qt Version -All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.15.2](https://github.com/bitcoin-core/gui-qml/blob/main/depends/packages/qt.mk#L2). +All development must adhere to the current upstream Qt Version to minimize our divergence from upstream and avoid costly changes. Review of open PR's must ensure that changes are compatible with this Qt version. Currently, the required version is [Qt 5.12.11](https://github.com/bitcoin-core/gui-qml/blob/a79a2249d027047f08dffe3f04951d52eac198f1/depends/packages/qt.mk#L2). As the Qt Version changes upstream, refactoring is allowed to use the now available features. -### Policies +# Compile and Run -This project has custom policies for development, see: -- [Icon Policy](./doc/icon-policy.md) -- [Translator Comments Policy](./doc/translator-comments.md) - -## Compile and Run - -The master branch is only guaranteed to work and build on Debian-based systems, Fedora, and macOS. +The master branch is only guaranteed to work and build on Debian-based systems and macOS. Support for more systems will be confirmed and documented as the project matures. ### Dependencies -No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. - -Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), the following additional dependencies are required to compile: - -#### Debian-based systems: +Aside from the dependencies listed in [build-unix.md](../../doc/build-unix.md), Debian based systems require the following additional dependencies to compile: ``` sudo apt install qtdeclarative5-dev qtquickcontrols2-5-dev @@ -69,23 +59,18 @@ they are not needed for static builds: sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` -#### Fedora: - -``` -sudo dnf install qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel -``` +No additional dependencies, besides those in [build-osx.md](../../doc/build-osx.md), are needed for macOS. ### Build -For instructions on how to build and compile Bitcoin Core, refer to your respective system's build doc. +For instructions on how to build and compile Bitcoin Core, refer to your respective systems build docs. -As long as the required dependencies are installed, the qml GUI will be built. -To ensure that you are in fact building the qml GUI, you can configure with the following option: +To add support for building the qml GUI, +you must configure with the following option: ``` ./configure --with-qml ``` - ### Run To run the qml GUI: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 8216255132..5e035677dd 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -42,12 +42,10 @@ QT_END_NAMESPACE #if defined(QT_STATICPLUGIN) #include -Q_IMPORT_PLUGIN(QtQmlPlugin) -Q_IMPORT_PLUGIN(QtQmlModelsPlugin) -Q_IMPORT_PLUGIN(QtQuick2Plugin) -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); +Q_IMPORT_PLUGIN(QtQuick2Plugin); +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 294768aec6..043d81bba0 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,7 +2,6 @@ components/BlockCounter.qml components/ConnectionOptions.qml - controls/Header.qml controls/OptionButton.qml controls/ProgressIndicator.qml pages/initerrormessage.qml diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..daefc91e52 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 21a3d3079d..f0d315f7b9 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../controls" ColumnLayout { @@ -31,13 +31,5 @@ ColumnLayout { Layout.fillWidth: true text: qsTr("Only when on Wi-Fi") description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") - detail: ProgressIndicator { - implicitWidth: 50 - SequentialAnimation on progress { - loops: Animation.Infinite - SmoothedAnimation { to: 1; velocity: 1; } - SmoothedAnimation { to: 0; velocity: 1; } - } - } } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml deleted file mode 100644 index 20dc80b3ac..0000000000 --- a/src/qml/controls/Header.qml +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property bool bold: false - property bool center: true - required property string header - property int headerMargin - property int headerSize: 28 - property string description - property int descriptionMargin: 10 - property int descriptionSize: 18 - property string subtext - property int subtextMargin - property int subtextSize: 15 - contentItem: ColumnLayout { - spacing: 0 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - topPadding: root.headerMargin - font.family: "Inter" - font.styleName: root.bold ? "Semi Bold" : "Regular" - font.pointSize: root.headerSize - color: "#FFFFFF" - text: root.header - horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - active: root.description.length > 0 - visible: active - sourceComponent: Label { - topPadding: root.descriptionMargin - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: root.descriptionSize - color: "#DEDEDE" - text: root.description - horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - active: root.subtext.length > 0 - visible: active - sourceComponent: Label { - topPadding: root.subtextMargin - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.subtextSize - color: "#FFFFFF" - text: root.subtext - horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap - } - } - } -} diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 0211a8fa7a..91281077d3 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 Button { property string description @@ -12,7 +12,6 @@ Button { id: button padding: 15 checkable: true - property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" @@ -29,53 +28,46 @@ Button { opacity: 0.4 } } - contentItem: RowLayout { + contentItem: ColumnLayout { spacing: 3 - ColumnLayout { - spacing: 3 - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: 18 - color: "white" - text: button.text - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 15 - color: "#DEDEDE" - text: button.description - wrapMode: Text.WordWrap - } - Loader { - Layout.topMargin: 2 - active: button.recommended - visible: active - sourceComponent: Label { - background: Rectangle { - color: "white" - radius: 3 - } - font.styleName: "Regular" - font.pixelSize: 13 - topPadding: 3 - rightPadding: 7 - bottomPadding: 4 - leftPadding: 7 - color: "black" - text: qsTr("Recommended") - } - } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pointSize: 18 + color: "white" + text: button.text + wrapMode: Text.WordWrap + } + Label { + Layout.fillWidth: true + Layout.preferredWidth: 0 + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: 15 + color: "#DEDEDE" + text: button.description + wrapMode: Text.WordWrap } Loader { - id: detail_loader - visible: item + Layout.topMargin: 2 + active: button.recommended + visible: active + sourceComponent: Label { + background: Rectangle { + color: "white" + radius: 3 + } + font.styleName: "Regular" + font.pixelSize: 13 + topPadding: 3 + rightPadding: 7 + bottomPadding: 4 + leftPadding: 7 + color: "black" + text: qsTr("Recommended") + } } } } diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..c58f402738 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Control { property real progress: 0 diff --git a/src/qml/nodemodel.cpp b/src/qml/nodemodel.cpp index 45601791df..b599eba066 100644 --- a/src/qml/nodemodel.cpp +++ b/src/qml/nodemodel.cpp @@ -23,6 +23,14 @@ void NodeModel::setBlockTipHeight(int new_height) } } +void NodeModel::setVerificationProgress(double new_progress) +{ + if (new_progress != m_verification_progress) { + m_verification_progress = new_progress; + Q_EMIT verificationProgressChanged(); + } +} + void NodeModel::startNodeInitializionThread() { Q_EMIT requestedInitialize(); @@ -37,13 +45,16 @@ void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::Bloc { // TODO: Handle the `success` parameter, setBlockTipHeight(tip_info.block_height); + setVerificationProgress(tip_info.verification_progress); } void NodeModel::ConnectToBlockTipSignal() { assert(!m_handler_notify_block_tip); + m_handler_notify_block_tip = m_node.handleNotifyBlockTip( [this](SynchronizationState state, interfaces::BlockTip tip, double verification_progress) { setBlockTipHeight(tip.block_height); + setVerificationProgress(verification_progress); }); } diff --git a/src/qml/nodemodel.h b/src/qml/nodemodel.h index b3190a0199..bc9f4a9f1a 100644 --- a/src/qml/nodemodel.h +++ b/src/qml/nodemodel.h @@ -21,12 +21,15 @@ class NodeModel : public QObject { Q_OBJECT Q_PROPERTY(int blockTipHeight READ blockTipHeight NOTIFY blockTipHeightChanged) + Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged) public: explicit NodeModel(interfaces::Node& node); int blockTipHeight() const { return m_block_tip_height; } void setBlockTipHeight(int new_height); + double verificationProgress() const { return m_verification_progress; } + void setVerificationProgress(double new_progress); Q_INVOKABLE void startNodeInitializionThread(); void startNodeShutdown(); @@ -38,10 +41,12 @@ public Q_SLOTS: void blockTipHeightChanged(); void requestedInitialize(); void requestedShutdown(); + void verificationProgressChanged(); private: // Properties that are exposed to QML. int m_block_tip_height{0}; + double m_verification_progress{0.0}; interfaces::Node& m_node; std::unique_ptr m_handler_notify_block_tip; diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index 109e51c1a0..e9d4ed8cb0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" import "../controls" @@ -28,18 +28,6 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 0 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 25 - } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From ac88e492b53825bf17c06e605d10830fcacb4568 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 6 Jan 2022 20:00:11 +0530 Subject: [PATCH 130/979] qml: Used verificationProgress in stub.qml - This commit uses the function added in previous commit to display the working progress bar in GUI - This commit also removes the tempory mouseClick event which used to change the progress meter when clicked. Rebased-From: bcea86c33ed98dfe11c6c7a8153032350c9165f8 Github-Pull: bitcoin-core/gui-qml#99 --- src/qml/pages/stub.qml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..1be7c5851b 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -35,10 +35,7 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } + progress: nodeModel.verificationProgress } ConnectionOptions { Layout.preferredWidth: 400 From f9a3ecccefdcab983ba29c8865e17be324ab085a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 18:55:22 +0200 Subject: [PATCH 131/979] Revert "qml: Used verificationProgress in stub.qml" This reverts commit bf4357cfe8fff26927870512666a656c7a6c0dab. Rebased-From: 06f3980bd8d5c36f485ce1cfa7bc802fb9a0fe66 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin_qml.qrc | 4 --- src/qml/components/ConnectionSettings.qml | 35 ------------------- src/qml/controls/ContinueButton.qml | 25 -------------- src/qml/controls/OptionSwitch.qml | 27 --------------- src/qml/controls/Setting.qml | 41 ----------------------- src/qml/pages/stub.qml | 5 ++- 6 files changed, 4 insertions(+), 133 deletions(-) delete mode 100644 src/qml/components/ConnectionSettings.qml delete mode 100644 src/qml/controls/ContinueButton.qml delete mode 100644 src/qml/controls/OptionSwitch.qml delete mode 100644 src/qml/controls/Setting.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 4c12fec837..294768aec6 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -2,13 +2,9 @@ components/BlockCounter.qml components/ConnectionOptions.qml - components/ConnectionSettings.qml - controls/ContinueButton.qml controls/Header.qml controls/OptionButton.qml - controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/Setting.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml deleted file mode 100644 index 5db05b5933..0000000000 --- a/src/qml/components/ConnectionSettings.qml +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 -import "../controls" - -ColumnLayout { - spacing: 20 - Setting { - Layout.fillWidth: true - header: "Use cellular data" - } - Setting { - Layout.fillWidth: true - header: "Daily upload limit" - } - Setting { - Layout.fillWidth: true - header: "Connection limit" - } - Setting { - Layout.fillWidth: true - header: "Listening enabled" - description: "Reduces data usage." - } - Setting { - last: true - Layout.fillWidth: true - header: "Blocks Only" - description: "Do not transfer unconfirmed transactions. Also disabled listening." - } -} diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml deleted file mode 100644 index 9f42e92bdf..0000000000 --- a/src/qml/controls/ContinueButton.qml +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Button { - font.family: "Inter" - font.styleName: "Semi Bold" - font.pointSize: 18 - contentItem: Text { - text: parent.text - font: parent.font - color: "white" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - background: Rectangle { - implicitHeight: 46 - implicitWidth: 300 - color: "#F7931A" - radius: 5 - } -} diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml deleted file mode 100644 index 947870a85d..0000000000 --- a/src/qml/controls/OptionSwitch.qml +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Switch { - id: root - indicator: Rectangle { - implicitWidth: 45 - implicitHeight: 28 - x: root.leftPadding - y: parent.height / 2 - height / 2 - radius: 18 - color: root.checked ? "#F7931A" : "#DDDDDD" - Rectangle { - id: indicatorButton - y: parent.height / 2 - height / 2 - x: root.checked ? parent.width - width - 4 : 0 + 4 - width: 20 - height: 20 - radius: 18 - color: "#ffffff" - } - } -} diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml deleted file mode 100644 index c636aa96c9..0000000000 --- a/src/qml/controls/Setting.qml +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property bool last: false - property string header - property string description - contentItem: GridLayout { - columns: 2 - rowSpacing: 20 - width: parent.width - Header { - Layout.fillWidth: true - center: false - header: root.header - headerSize: 18 - description: root.description - descriptionSize: 15 - descriptionMargin: 0 - } - OptionSwitch { - Layout.alignment: Qt.AlignRight - } - Loader { - Layout.fillWidth:true - Layout.columnSpan: 2 - active: !last - visible: active - sourceComponent: Rectangle { - height: 1 - color: "#777777" - } - } - } -} diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,7 +47,10 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: nodeModel.verificationProgress + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } } ConnectionOptions { Layout.preferredWidth: 400 From a86315aab97b3e2f2921f1cfad724b9ac2ad63ab Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:03:27 +0200 Subject: [PATCH 132/979] Revert "qml: demo Header control" This reverts commit 11755e87b8f5359b45987e515ce20a318ac5d1de. Rebased-From: 7ca1f5d2151a3a0bb58da92e4e002cc53d95d1ec Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..a3f36376d9 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -28,18 +28,6 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 0 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 25 - } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From 5e4558d7c88be8bdbdd143dd255c4819287b2d91 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:04:43 +0200 Subject: [PATCH 133/979] Revert "scripted-diff: Bump Qt Quick module versions" This reverts commit 447a46bbb0f4925a2231d9e5e2cd71ce5a8633b1. Rebased-From: 2c55ef95bb7bb3d4519ed97fc0ab8c6dc589ced9 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/components/BlockCounter.qml | 4 ++-- src/qml/components/ConnectionOptions.qml | 6 +++--- src/qml/controls/OptionButton.qml | 6 +++--- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/pages/initerrormessage.qml | 4 ++-- src/qml/pages/stub.qml | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..daefc91e52 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 21a3d3079d..b8ad56fa1c 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../controls" ColumnLayout { diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 0211a8fa7a..866333c056 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..c58f402738 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index 109e51c1a0..e9d4ed8cb0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a3f36376d9..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" import "../controls" From edff6e1b50762ac7b7d436850087db41a41d9a16 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:04:55 +0200 Subject: [PATCH 134/979] Revert "qml: Demo ProgressIndicator control" This reverts commit dd0436119c98e0d6221e272029ad132fad9982a1. Rebased-From: e740620b9925bc0e48b49cf636e73df5195c4b6b Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From c6b86bd624da2cb7e22053131edf509cddec732d Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:05:04 +0200 Subject: [PATCH 135/979] Revert "qml: Show ConnectionOptions" This reverts commit 7dde535fb0be147afab7f6b36eb4dcacf2e556bf. Rebased-From: 5c065e234dbcda7272b5b855c3008e4b873a09e3 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,9 +31,5 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } } } From c0c5691d84b9e101ab7786e8f5a89eb5e96a2352 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:05:19 +0200 Subject: [PATCH 136/979] Revert "qml: Use ColumnLayout in application window" This reverts commit 83e152fb823f6859c9ae881ea9a15bfda7a07689. Rebased-From: 772515cdffdc9161a99566f1bb879073a199e12c Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,19 +17,17 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - ColumnLayout { + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + + BlockCounter { + id: blockCounter anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } + blockHeight: nodeModel.blockTipHeight } } From bd2fc7f717cf31589f1be209bcaf52afc1d73eb6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:05:48 +0200 Subject: [PATCH 137/979] Revert "qml: Drop import qualifier BitcoinCoreComponents" This reverts commit 9d811fa957e630c4468bf9a06d4c3dffa039d785. Rebased-From: 2eec3137996dfb9746517e679484354b6daea0a3 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,7 +5,8 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow @@ -25,7 +26,7 @@ ApplicationWindow { sourceSize.height: 128 } - BlockCounter { + BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From a1f8753437b1e2111ff7fc4121abb420de9cb211 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:06:16 +0200 Subject: [PATCH 138/979] Revert "doc: Drop unneeded runtime dependencies" This reverts commit 38e19e22aaebcb7c7a32d3e54b528b78e4ccf3cb. Rebased-From: ca776c8306ed264bfcc2002cdcda038943a502d5 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..03534e7cd9 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` #### Fedora: From 948a2f558f1ef0adbc5ff9a1b70dd8721b8a223e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:06:48 +0200 Subject: [PATCH 139/979] Revert "multiprocess: add new bitcoin-qt init implementation to qml-gui" This reverts commit 8b6efe6555868f0e99bf5bcadbb53cb785c6fb68. Rebased-From: 5dce58687981cbe6cdbd423a983936e2d22e1623 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4cea873af2..1982f5e1a2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -103,12 +104,15 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 3ae5a2734fe3ba09e88275110642403e7d69464a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:06:56 +0200 Subject: [PATCH 140/979] Revert "qml: Set tab focus behavior" This reverts commit 9a106972d3ec8f63e4220b2c9baad5463ab923e3. Rebased-From: 3e5398e8a9c96784c9af1c0f6751cb553de823aa Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 1982f5e1a2..9ce622ba07 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE @@ -99,7 +98,6 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 70e9ae04c34cc405e3bc52453f49aa0369cb2845 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:07:12 +0200 Subject: [PATCH 141/979] Revert "qml: Drop erroneous `#include `" This reverts commit 8e3abe6de1eacfd68feff354b3a8414fd4c971dd. Rebased-From: a12952d3f4466908a6af1e9be6dfed1bdfc9417c Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9ce622ba07..73406c652d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE From 5ce0e1acfcc89aca64a56513773446f63a78e3cf Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:07:28 +0200 Subject: [PATCH 142/979] Revert "qml, doc: Add import QtQuick.Layouts" This reverts commit 498572decde7ce341f2ee6b44c286c4c86bfdec8. Rebased-From: e525147ae7d59d0eef5e44f28541fcceda458586 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 - src/qml/pages/stub.qml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 03534e7cd9..21aa7ea417 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 ``` #### Fedora: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 73406c652d..a281d04306 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -47,7 +47,6 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..7a56f6ce3a 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,7 +4,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From 9319c0768e2c0eac1ecf39e66fd1296d9777dcca Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:07:41 +0200 Subject: [PATCH 143/979] Revert "qml: Add qInstallMessageHandler" This reverts commit 864dc9476d35cfa033ffed48342cc2d6e534192c. Rebased-From: 47de82740f0e3f75beb2fd9fe89b7125f1b86f62 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index a281d04306..7f5a21b99e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -33,14 +32,9 @@ #include #include #include -#include #include #include -QT_BEGIN_NAMESPACE -class QMessageLogContext; -QT_END_NAMESPACE - #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQmlPlugin) @@ -74,17 +68,6 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } - -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); - } -} } // namespace @@ -195,9 +178,6 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); - qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); node_model.startShutdownPolling(); From 752231cfcabd331c2be2eff8a2adf17104ff5a74 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:08:10 +0200 Subject: [PATCH 144/979] Revert "build, qml: Add qtquickcontrols2 module" This reverts commit 01398aebabfeaba87be96f477f6a618123bf0ebc. Rebased-From: 20332272c435148957dd2977e3528912a20fa056 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7f5a21b99e..85a498015d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,8 +41,6 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From da834597063a4f8a326240aaed25c733db3bb5e8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 9 Jan 2022 19:08:17 +0200 Subject: [PATCH 145/979] Revert "build, qml: Add qtdeclarative module" This reverts commit ed3e4cfd39e0b67cf8d050a6dd791dabe1339647. Rebased-From: 9ca70f601744a1cbf4916313ed5092c7e913f171 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 85a498015d..258f73f01f 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,14 +35,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQmlPlugin) -Q_IMPORT_PLUGIN(QtQmlModelsPlugin) -Q_IMPORT_PLUGIN(QtQuick2Plugin) -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { From 479019aa1aa35b250547dac8699bb9614b709dfe Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:50:48 +0300 Subject: [PATCH 146/979] build, qml: Add qtdeclarative module QML features are mentioned in the `qt.mk` file explicitly for easy reference. The only exception is the qml-jit feature, the availability of which depends on the host platform. Rebased-From: 63e623c6e106702d8717949923c86cb700c61d77 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 258f73f01f..85a498015d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,6 +35,14 @@ #include #include +#if defined(QT_STATICPLUGIN) +#include +Q_IMPORT_PLUGIN(QtQmlPlugin) +Q_IMPORT_PLUGIN(QtQmlModelsPlugin) +Q_IMPORT_PLUGIN(QtQuick2Plugin) +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +#endif + namespace { void SetupUIArgs(ArgsManager& argsman) { From a8e622cd9b57d0098920de6c9151d9e9809572b1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:54:11 +0300 Subject: [PATCH 147/979] build, qml: Add qtquickcontrols2 module Rebased-From: 47c2e6342ab92f6732352607266f86e75047ddf1 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 85a498015d..7f5a21b99e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,6 +41,8 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From 36010cc79c79ba2649b8e5ffe3648bf623203791 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:13:33 +0300 Subject: [PATCH 148/979] qml: Add qInstallMessageHandler Rebased-From: b8413e581bc5b96edf05a559bc350ccd275b3a17 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7f5a21b99e..a281d04306 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,14 @@ #include #include #include +#include #include #include +QT_BEGIN_NAMESPACE +class QMessageLogContext; +QT_END_NAMESPACE + #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQmlPlugin) @@ -68,6 +74,17 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } + +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } +} } // namespace @@ -178,6 +195,9 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + // Install qDebug() message handler to route to debug.log + qInstallMessageHandler(DebugMessageHandler); + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); node_model.startShutdownPolling(); From be17ceaa51defcfd35d22e2a1e81489d65717408 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 3 Oct 2021 14:32:13 +0300 Subject: [PATCH 149/979] qml, doc: Add import QtQuick.Layouts Rebased-From: 6c58ae5fa0bcc491e2c3caaddf1a77f32980fdcf Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 + src/qml/pages/stub.qml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 21aa7ea417..03534e7cd9 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` #### Fedora: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index a281d04306..73406c652d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -47,6 +47,7 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 7a56f6ce3a..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,6 +4,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From cb48138eae112b49c64ba889418bf09a543a4727 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:33:02 +0300 Subject: [PATCH 150/979] qml: Drop erroneous `#include ` To use the `QStringLiteral` macro, the `QString` header should be included, that is done already. Rebased-From: 055e5c79e5818898a4b511a199dbe81b2e47692b Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 73406c652d..9ce622ba07 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE From d8c611765b177643562827ee70822c4542469391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:20:03 +0100 Subject: [PATCH 151/979] qml: Set tab focus behavior Rebased-From: c7647c53b117d024fba92a78dbd0db081008e974 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9ce622ba07..1982f5e1a2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -98,6 +99,7 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 98b05779d6fea5685469223f7902496750f6a3e0 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 27 Oct 2021 14:49:32 -0400 Subject: [PATCH 152/979] multiprocess: add new bitcoin-qt init implementation to qml-gui This incorporates the new bitcoin-qt init implementation into the qml-gui. Rebased-From: 90305f62a405d1cae31c6d68781d85735fe50cd4 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/bitcoin.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 1982f5e1a2..4cea873af2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -104,15 +103,12 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 522a8822b87a464c631fce592d5c48d2cd321168 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Oct 2021 14:17:44 +0300 Subject: [PATCH 153/979] doc: Drop unneeded runtime dependencies Rebased-From: 641f2a575db51e82f26a9076843ab8fac418ee13 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 03534e7cd9..6fae9f9194 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` #### Fedora: From bbddf70739b1cef5982ad73c451ae0801366f9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:10:14 +0100 Subject: [PATCH 154/979] qml: Drop import qualifier BitcoinCoreComponents Rebased-From: 5d4ded43092a55aa246792a6085159d6956f9523 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,8 +5,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" as BitcoinCoreComponents - +import "../components" ApplicationWindow { id: appWindow @@ -26,7 +25,7 @@ ApplicationWindow { sourceSize.height: 128 } - BitcoinCoreComponents.BlockCounter { + BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From 740aa4364b8935f1892f467dda799962c91bda6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:44:47 +0100 Subject: [PATCH 155/979] qml: Use ColumnLayout in application window Rebased-From: 126df091fbff6fe6a22a866cf3cecd5e48769740 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,17 +17,19 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - Image { - id: appLogo - anchors.horizontalCenter: parent.horizontalCenter - source: "image://images/app" - sourceSize.width: 128 - sourceSize.height: 128 - } - - BlockCounter { - id: blockCounter + ColumnLayout { anchors.centerIn: parent - blockHeight: nodeModel.blockTipHeight + spacing: 15 + width: 400 + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } } } From da354b546c7487c8dec57132d3b2add8e6d928c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:46:48 +0100 Subject: [PATCH 156/979] qml: Show ConnectionOptions Rebased-From: b21b3c9da34fbe45032b337c340342da730549c0 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,5 +31,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ConnectionOptions { + Layout.preferredWidth: 400 + focus: true + } } } From cf1a02a85060dfb44153cd42eef84475b6159ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:48:06 +0100 Subject: [PATCH 157/979] qml: Demo ProgressIndicator control Rebased-From: 56298863e52f8521a1197c7fdfc0bfadf52c58d3 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,6 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" +import "../controls" ApplicationWindow { id: appWindow @@ -31,6 +32,14 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ProgressIndicator { + id: indicator + Layout.fillWidth: true + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } + } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 45bdbdd105409e4a13becb00176cb2a5d003c08c Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 24 Dec 2021 12:04:23 +0200 Subject: [PATCH 158/979] scripted-diff: Bump Qt Quick module versions -BEGIN VERIFY SCRIPT- QML_FILES=$(git ls-files '*.qml') sed -i -e 's/import QtQuick 2.12/import QtQuick 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Controls 2.12/import QtQuick.Controls 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Layouts 1.11/import QtQuick.Layouts 1.15/' -- $QML_FILES -END VERIFY SCRIPT- Rebased-From: e495a83318d2a4828a1a2f322c5e782d37ebc643 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/components/BlockCounter.qml | 4 ++-- src/qml/components/ConnectionOptions.qml | 6 +++--- src/qml/controls/OptionButton.qml | 6 +++--- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/pages/initerrormessage.qml | 4 ++-- src/qml/pages/stub.qml | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index daefc91e52..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index b8ad56fa1c..21a3d3079d 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import "../controls" ColumnLayout { diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 866333c056..0211a8fa7a 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index c58f402738..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index e9d4ed8cb0..109e51c1a0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..a3f36376d9 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import "../components" import "../controls" From 2cd15532bc6ca11ed16eed15183d60e4a49714b8 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Sun, 2 Jan 2022 22:59:24 -0500 Subject: [PATCH 159/979] qml: demo Header control Rebased-From: f80373023608303ef8c6c08c44c3915be2817aa2 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a3f36376d9..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -28,6 +28,18 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 0 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 25 + } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From 4231ac96128a75cce3b7b762385778d9c1c4be82 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 6 Jan 2022 20:00:11 +0530 Subject: [PATCH 160/979] qml: Used verificationProgress in stub.qml - This commit uses the function added in previous commit to display the working progress bar in GUI - This commit also removes the tempory mouseClick event which used to change the progress meter when clicked. Rebased-From: dbf77f268bd64e53519d513cc0de22bf8a492bc7 Github-Pull: bitcoin-core/gui-qml#110 --- src/qml/pages/stub.qml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,10 +47,7 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } + progress: nodeModel.verificationProgress } ConnectionOptions { Layout.preferredWidth: 400 From 5510af69435ebe5b6c873b27df8d4265219239b3 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 5 Jan 2022 18:50:34 -0500 Subject: [PATCH 161/979] qml: refactor OptionButton to utilize Header control This simplifies the OptionButton control. Rebased-From: 1fc34de4e57a6caaec2ce7cfc3c73dda9dcc4332 Github-Pull: bitcoin-core/gui-qml#102 --- src/qml/controls/OptionButton.qml | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 0211a8fa7a..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -33,25 +33,16 @@ Button { spacing: 3 ColumnLayout { spacing: 3 - Label { + Header { Layout.fillWidth: true Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pointSize: 18 - color: "white" - text: button.text - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - Layout.preferredWidth: 0 - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: 15 - color: "#DEDEDE" - text: button.description - wrapMode: Text.WordWrap + center: false + header: button.text + headerSize: 18 + headerMargin: 0 + description: button.description + descriptionSize: 15 + descriptionMargin: 0 } Loader { Layout.topMargin: 2 From 3f0f7d206b01a56a3bd2c49c831fbd5e4fb344e1 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Tue, 4 Jan 2022 11:59:35 -0500 Subject: [PATCH 162/979] qml: introduce StorageOptions component Rebased-From: 26a616d208d29e0ef4aa1b80ac69cc2549c58f2e Github-Pull: bitcoin-core/gui-qml#102 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/components/StorageOptions.qml | 37 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/qml/components/StorageOptions.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 4c12fec837..214d255f5c 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -3,6 +3,7 @@ components/BlockCounter.qml components/ConnectionOptions.qml components/ConnectionSettings.qml + components/StorageOptions.qml controls/ContinueButton.qml controls/Header.qml controls/OptionButton.qml diff --git a/src/qml/components/StorageOptions.qml b/src/qml/components/StorageOptions.qml new file mode 100644 index 0000000000..a335628ac7 --- /dev/null +++ b/src/qml/components/StorageOptions.qml @@ -0,0 +1,37 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + ButtonGroup { + id: group + } + spacing: 15 + OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + text: qsTr("Reduce storage") + description: qsTr("Uses about 75GB.") + recommended: true + checked: true + detail: ProgressIndicator { + implicitWidth: 75 + progress: 0.25 + } + } + OptionButton { + ButtonGroup.group: group + Layout.fillWidth: true + text: qsTr("Default") + description: qsTr("Uses about 423GB.") + detail: ProgressIndicator { + implicitWidth: 75 + progress: 0.8 + } + } +} From ad371b1f03330f389a84c4147feb585f9e7549cd Mon Sep 17 00:00:00 2001 From: jarolrod Date: Tue, 4 Jan 2022 12:02:28 -0500 Subject: [PATCH 163/979] qml: introduce TextButton control Rebased-From: f440d8294318a57676a50733c5453583d93bd5b9 Github-Pull: bitcoin-core/gui-qml#102 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/TextButton.qml | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/qml/controls/TextButton.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 214d255f5c..fde4e5af3b 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,6 +10,7 @@ controls/OptionSwitch.qml controls/ProgressIndicator.qml controls/Setting.qml + controls/TextButton.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml new file mode 100644 index 0000000000..bc15172f2b --- /dev/null +++ b/src/qml/controls/TextButton.qml @@ -0,0 +1,23 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Button { + id: root + property int textSize: 18 + property string textColor: "white" + font.family: "Inter" + font.styleName: "Semi Bold" + font.pointSize: root.textSize + contentItem: Text { + text: root.text + font: root.font + color: root.textColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + background: null +} From 28df8997bd815143055573779fd7934ca4b13bd5 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 13 Jan 2022 21:15:16 +0530 Subject: [PATCH 164/979] qml: Using qsTr() with strings in ConnectionSettings.qml Rebased-From: fe41329c66f93bb63a086551bce8f29f9c641b3f Github-Pull: bitcoin-core/gui-qml#112 --- src/qml/components/ConnectionSettings.qml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml index 5db05b5933..35f8e5d3ab 100644 --- a/src/qml/components/ConnectionSettings.qml +++ b/src/qml/components/ConnectionSettings.qml @@ -11,25 +11,25 @@ ColumnLayout { spacing: 20 Setting { Layout.fillWidth: true - header: "Use cellular data" + header: qsTr("Use cellular data") } Setting { Layout.fillWidth: true - header: "Daily upload limit" + header: qsTr("Daily upload limit") } Setting { Layout.fillWidth: true - header: "Connection limit" + header: qsTr("Connection limit") } Setting { Layout.fillWidth: true - header: "Listening enabled" - description: "Reduces data usage." + header: qsTr("Listening enabled") + description: qsTr("Reduces data usage.") } Setting { last: true Layout.fillWidth: true - header: "Blocks Only" - description: "Do not transfer unconfirmed transactions. Also disabled listening." + header: qsTr("Blocks Only") + description: qsTr("Do not transfer unconfirmed transactions. Also disabled listening.") } } From 9bfc38d80bdbcf3d2a7c468779bd3a495a370745 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 13 Jan 2022 21:17:27 +0530 Subject: [PATCH 165/979] qml: Use Math.round() in OptionSwitch.qml Rebased-From: be87ba9c1c5a99cdc7df684b2a0752947a484947 Github-Pull: bitcoin-core/gui-qml#112 --- src/qml/controls/OptionSwitch.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index 947870a85d..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -11,7 +11,7 @@ Switch { implicitWidth: 45 implicitHeight: 28 x: root.leftPadding - y: parent.height / 2 - height / 2 + y: Math.round((parent.height - height) / 2) radius: 18 color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { From 59d19a965795551a5efe67568c4ba96a53a331c4 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 13 Jan 2022 21:22:07 +0530 Subject: [PATCH 166/979] qml: Replace GridLayout with nested Column Row Layout in Settings.qml Rebased-From: a0ba0d7dc762f0f92087e989c241a112cd6c7aea Github-Pull: bitcoin-core/gui-qml#112 --- src/qml/controls/Setting.qml | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index c636aa96c9..f7eef1bd87 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -11,21 +11,22 @@ Control { property bool last: false property string header property string description - contentItem: GridLayout { - columns: 2 - rowSpacing: 20 + contentItem: ColumnLayout { + spacing: 20 width: parent.width - Header { - Layout.fillWidth: true - center: false - header: root.header - headerSize: 18 - description: root.description - descriptionSize: 15 - descriptionMargin: 0 - } - OptionSwitch { - Layout.alignment: Qt.AlignRight + RowLayout { + Header { + Layout.fillWidth: true + center: false + header: root.header + headerSize: 18 + description: root.description + descriptionSize: 15 + descriptionMargin: 0 + } + OptionSwitch { + Layout.alignment: Qt.AlignRight + } } Loader { Layout.fillWidth:true From 3bb8b60bad214599a648d6e34d91ce09d2dbbd0c Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 13 Jan 2022 21:23:40 +0530 Subject: [PATCH 167/979] qml: Make further suggested changes to Settings.qml - Modified property last so that it can automatically be derived by root positioning in parent element. - Made header property to be necessarily required. Rebased-From: f5458f2c63ef201eddf112729da66d7c1f2f86f1 Github-Pull: bitcoin-core/gui-qml#112 --- src/qml/controls/Setting.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index f7eef1bd87..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -8,8 +8,8 @@ import QtQuick.Layouts 1.15 Control { id: root - property bool last: false - property string header + property bool last: parent && root === parent.children[parent.children.length - 1] + required property string header property string description contentItem: ColumnLayout { spacing: 20 From c5e49c4b7ed2b7747a0c528ba8d64ce6ded07031 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Tue, 4 Jan 2022 13:19:35 -0500 Subject: [PATCH 168/979] qml: introduce PageIndicator control Rebased-From: 563ee6816a3609a61ac4fc0816aeac619a21c1ef Github-Pull: bitcoin-core/gui-qml#113 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/PageIndicator.qml | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/qml/controls/PageIndicator.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index fde4e5af3b..fde697d1cf 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -6,6 +6,7 @@ components/StorageOptions.qml controls/ContinueButton.qml controls/Header.qml + controls/PageIndicator.qml controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml new file mode 100644 index 0000000000..29e2ac49c0 --- /dev/null +++ b/src/qml/controls/PageIndicator.qml @@ -0,0 +1,22 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +PageIndicator { + id: root + delegate: Rectangle { + implicitWidth: 10 + implicitHeight: 10 + radius: Math.round(width / 2) + color: "white" + opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 + Behavior on opacity { + OpacityAnimator { + duration: 100 + } + } + } +} From d9f6fa2d26060b0ca1546bb717f6e9a1532a42f3 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Thu, 6 Jan 2022 15:58:28 -0500 Subject: [PATCH 169/979] qml: introduce Theme singleton Holds color definitions and updates based on if in dark mode. Rebased-From: e0225a0719e12cb26ee17d3c657da0101ac22a99 Github-Pull: bitcoin-core/gui-qml#114 --- src/qml/bitcoin_qml.qrc | 2 ++ src/qml/controls/Theme.qml | 28 ++++++++++++++++++++++++++++ src/qml/controls/qmldir | 1 + 3 files changed, 31 insertions(+) create mode 100644 src/qml/controls/Theme.qml create mode 100644 src/qml/controls/qmldir diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index fde697d1cf..ee5a1e250e 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,8 +10,10 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml + controls/qmldir controls/Setting.qml controls/TextButton.qml + controls/Theme.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml new file mode 100644 index 0000000000..0542f84120 --- /dev/null +++ b/src/qml/controls/Theme.qml @@ -0,0 +1,28 @@ +pragma Singleton +import QtQuick 2.15 + +QtObject { + property bool dark: false + property QtObject color: QtObject { + property color white: "#FFFFFF" + property color background: dark ? "black" : "white" + property color orange: dark ? "#F89B2A" : "#F7931A" + property color red: dark ? "#EC6363" : "#EB5757" + property color green: dark ? "#36B46B" : "#27AE60" + property color blue: dark ? "#3CA3DE" : "#2D9CDB" + property color purple: dark ? "#C075DC" : "#BB6BD9" + property color neutral0: dark ? "#000000" : "#FFFFFF" + property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" + property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" + property color neutral3: dark ? "#444444" : "#EDEDED" + property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" + property color neutral5: dark ? "#787878" : "#BBBBBB" + property color neutral6: dark ? "#949494" : "#999999" + property color neutral7: dark ? "#B0B0B0" : "#777777" + property color neutral8: dark ? "#CCCCCC" : "#404040" + property color neutral9: dark ? "#FFFFFF" : "#000000" + } + function toggleDark() { + dark = !dark + } +} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir new file mode 100644 index 0000000000..d57fb8673e --- /dev/null +++ b/src/qml/controls/qmldir @@ -0,0 +1 @@ +singleton Theme 1.0 Theme.qml From 40891d770f99697126ddcd3638c4b1b2976a8fa5 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Thu, 6 Jan 2022 16:00:19 -0500 Subject: [PATCH 170/979] qml: update UI elements to use Theme color definitions Rebased-From: 9b9d198407118475d6ba6dd315991f2a42c813b0 Github-Pull: bitcoin-core/gui-qml#114 --- src/qml/components/BlockCounter.qml | 5 +++-- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 ++++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/pages/stub.qml | 2 +- 10 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..cf8cc79d22 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,13 +6,14 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 +import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: "black" + color: Theme.color.background } - color: "orange" + color: Theme.color.orange padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 9f42e92bdf..2b98f8baff 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: "white" + color: Theme.color.white horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: "#F7931A" + color: Theme.color.orange radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 20dc80b3ac..13d42e1c43 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: "#FFFFFF" + color: Theme.color.neutral9 text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: "#DEDEDE" + color: Theme.color.neutral8 text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: "#FFFFFF" + color: Theme.color.neutral9 text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index e6f83202fe..56d07cb407 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" + border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: "#F7931A" + border.color: Theme.color.orange radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: "white" + color: Theme.color.neutral9 radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: "black" + color: Theme.color.neutral0 text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index 3e71039fdf..b54660c276 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? "#F7931A" : "#DDDDDD" + color: root.checked ? Theme.color.orange : Theme.color.neutral4 Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: "#ffffff" + color: Theme.color.white } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 29e2ac49c0..751d251d94 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: "white" + color: Theme.color.neutral9 opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..117a4baebb 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: "#404040" + color: Theme.color.neutral3 Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: "orange" + color: Theme.color.orange } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index d0b97f68d5..52dc1f706d 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: "#777777" + color: Theme.color.neutral5 } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index bc15172f2b..1063a275ba 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: "white" + property string textColor: Theme.color.neutral9 font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..61baf5e2cf 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: "black" + color: Theme.color.background visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); From f105ee4e64f186ac9a996d31df5525eff8f7f109 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 25 May 2022 00:08:38 -0400 Subject: [PATCH 171/979] doc: fix link to optimize-pngs.py script Rebased-From: cca1acfe7802860e542ade973ed8b94d15ae6945 Github-Pull: bitcoin-core/gui-qml#116 --- src/qml/bitcoin_qml.qrc | 2 -- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 ++++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/controls/Theme.qml | 28 -------------------------- src/qml/controls/qmldir | 1 - src/qml/doc/icon-policy.md | 2 +- src/qml/pages/stub.qml | 2 +- 14 files changed, 20 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/Theme.qml delete mode 100644 src/qml/controls/qmldir diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index ee5a1e250e..fde697d1cf 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,10 +10,8 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/qmldir controls/Setting.qml controls/TextButton.qml - controls/Theme.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml deleted file mode 100644 index 0542f84120..0000000000 --- a/src/qml/controls/Theme.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -QtObject { - property bool dark: false - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" - } - function toggleDark() { - dark = !dark - } -} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir deleted file mode 100644 index d57fb8673e..0000000000 --- a/src/qml/controls/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Theme 1.0 Theme.qml diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md index 2152f0bde6..a07ba6a12b 100644 --- a/src/qml/doc/icon-policy.md +++ b/src/qml/doc/icon-policy.md @@ -17,7 +17,7 @@ PNGs are used in production due to wide application support, transparency suppor and better image quality compared to competing file types such as JPEG. #### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. +Production (PNG) files must be processed by the [optimize-pngs.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimize-pngs.py) script before their inclusion in Bitcoin Core. PNG optimization removes various unnecessary color profiles, ancillary data, and text chunks, resulting in a lossless file size reduction. diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); From 8a91bcf38168e4d9db1ffb2468e901fc35fc1fca Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 25 May 2022 00:37:22 -0400 Subject: [PATCH 172/979] qml: introduce info icon Introduces the info icon from the Bitcoin Icons set. Optimized with the optimize-pngs.py script. Since this is the first icon being added, also adds inclusion of icons to builds. Rebased-From: c11be3a2f38c178a15d3becd03e1ac42ba21af8d Github-Pull: bitcoin-core/gui-qml#117 --- src/qml/bitcoin_qml.qrc | 3 +-- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 +++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/controls/Theme.qml | 28 ------------------------- src/qml/controls/qmldir | 1 - src/qml/doc/icon-policy.md | 2 +- src/qml/imageprovider.cpp | 5 +++++ src/qml/pages/stub.qml | 2 +- src/qml/res/icons/info.png | Bin 0 -> 301 bytes src/qml/res/src/info.svg | 4 ++++ 17 files changed, 30 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/Theme.qml delete mode 100644 src/qml/controls/qmldir create mode 100644 src/qml/res/icons/info.png create mode 100644 src/qml/res/src/info.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index ee5a1e250e..f77d14e20e 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,15 +10,14 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/qmldir controls/Setting.qml controls/TextButton.qml - controls/Theme.qml pages/initerrormessage.qml pages/stub.qml ../qt/res/icons/bitcoin.png + res/icons/info.png res/fonts/Inter-Regular.otf diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml deleted file mode 100644 index 0542f84120..0000000000 --- a/src/qml/controls/Theme.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -QtObject { - property bool dark: false - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" - } - function toggleDark() { - dark = !dark - } -} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir deleted file mode 100644 index d57fb8673e..0000000000 --- a/src/qml/controls/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Theme 1.0 Theme.qml diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md index a07ba6a12b..2152f0bde6 100644 --- a/src/qml/doc/icon-policy.md +++ b/src/qml/doc/icon-policy.md @@ -17,7 +17,7 @@ PNGs are used in production due to wide application support, transparency suppor and better image quality compared to competing file types such as JPEG. #### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-pngs.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimize-pngs.py) script before their inclusion in Bitcoin Core. +Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. PNG optimization removes various unnecessary color profiles, ancillary data, and text chunks, resulting in a lossless file size reduction. diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 88c9cae72a..71bf2d34ff 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -27,5 +27,10 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return m_network_style->getAppIcon().pixmap(requested_size); } + if (id == "info") { + *size = requested_size; + return QIcon(":/icons/info").pixmap(requested_size); + } + return {}; } diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); diff --git a/src/qml/res/icons/info.png b/src/qml/res/icons/info.png new file mode 100644 index 0000000000000000000000000000000000000000..03c3997d2de8de1198f3380035d6438d874f616a GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2_TxFP<)rAr*{ouQIx^1cj6f4W;D`C; zm}iFZuWg?wT^89q{ri^Qy{YD{Z&Idy%U+$cyu&l@vQ_m-6;+ufyxZmrO*_mGuK6%e z;(?j!9UkVG*J8zxWLF!lVqpYk)8b$rfi*etSX%}+)%+2=o>|5z@wbV(%N_1UZp yE0X8^KKD#BdE&L3P7I7J0uH1R5SKDE*#BUA>FIskdUXVpUXO@geCyvC}uwZ literal 0 HcmV?d00001 diff --git a/src/qml/res/src/info.svg b/src/qml/res/src/info.svg new file mode 100644 index 0000000000..236b78c2fd --- /dev/null +++ b/src/qml/res/src/info.svg @@ -0,0 +1,4 @@ + + + + From 7c4c104db55f636be60cdfadd1a16ccf2981b322 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 25 May 2022 01:18:48 -0400 Subject: [PATCH 173/979] qml: introduce caret-left icon Rebased-From: f4c87526c6cfa768453998fd794db3caabe799e1 Github-Pull: bitcoin-core/gui-qml#118 --- src/qml/bitcoin_qml.qrc | 3 +-- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 +++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/controls/Theme.qml | 28 ------------------------- src/qml/controls/qmldir | 1 - src/qml/doc/icon-policy.md | 2 +- src/qml/imageprovider.cpp | 5 +++++ src/qml/pages/stub.qml | 2 +- src/qml/res/icons/caret-left.png | Bin 0 -> 385 bytes src/qml/res/src/caret-left.svg | 3 +++ 17 files changed, 29 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/Theme.qml delete mode 100644 src/qml/controls/qmldir create mode 100644 src/qml/res/icons/caret-left.png create mode 100644 src/qml/res/src/caret-left.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 90b0658da6..5985b255b0 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,15 +10,14 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/qmldir controls/Setting.qml controls/TextButton.qml - controls/Theme.qml pages/initerrormessage.qml pages/stub.qml ../qt/res/icons/bitcoin.png + res/icons/caret-left.png res/icons/info.png diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml deleted file mode 100644 index 0542f84120..0000000000 --- a/src/qml/controls/Theme.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -QtObject { - property bool dark: false - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" - } - function toggleDark() { - dark = !dark - } -} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir deleted file mode 100644 index d57fb8673e..0000000000 --- a/src/qml/controls/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Theme 1.0 Theme.qml diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md index a07ba6a12b..2152f0bde6 100644 --- a/src/qml/doc/icon-policy.md +++ b/src/qml/doc/icon-policy.md @@ -17,7 +17,7 @@ PNGs are used in production due to wide application support, transparency suppor and better image quality compared to competing file types such as JPEG. #### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-pngs.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimize-pngs.py) script before their inclusion in Bitcoin Core. +Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. PNG optimization removes various unnecessary color profiles, ancillary data, and text chunks, resulting in a lossless file size reduction. diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 71bf2d34ff..5e03d2df2a 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -27,6 +27,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return m_network_style->getAppIcon().pixmap(requested_size); } + if (id == "caret-left") { + *size = requested_size; + return QIcon(":/icons/caret-left").pixmap(requested_size); + } + if (id == "info") { *size = requested_size; return QIcon(":/icons/info").pixmap(requested_size); diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); diff --git a/src/qml/res/icons/caret-left.png b/src/qml/res/icons/caret-left.png new file mode 100644 index 0000000000000000000000000000000000000000..7a8ad063095835388a36289fde37a4ac1b2c2b58 GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-FnV~pIEGX(zP)Uk6c8xE`taag zYp*?rVy`=RwqCW+VM!N#!=PoAlpAwvM|Iw*3eod3->-Xc=C}ML6;Ci)yPEmVQ^j_U zuan}qS{3btUdX0itDa`NKVY)$euHCtNqd&+ROn{L*Z=!H$##EJ^UmY(E1t0k&Us(+ z-1`2{bLDpD)DKxhnEO7@1&Xp4Kxm+BNKp?*|4g5Mztkl?{{8x(T>Ve4s;FQ7LExwB z>=kDDb+OlKDs1%+=pV9~DZZfnw98JHncuB83FR!-wLPeQs_FXK(xf+w8za5E21k~2JTh(&gepZ^ExP4z8$+Z;cM@@$ZuB>acttToJZLy%N<|kJuCu)ydJ7n|44$rjF6*2UngCHTs8av{ literal 0 HcmV?d00001 diff --git a/src/qml/res/src/caret-left.svg b/src/qml/res/src/caret-left.svg new file mode 100644 index 0000000000..3af3b06243 --- /dev/null +++ b/src/qml/res/src/caret-left.svg @@ -0,0 +1,3 @@ + + + From 0a31a639261b5f50630bfde692ac619b354428b2 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 25 May 2022 01:46:18 -0400 Subject: [PATCH 174/979] qml: introduce caret-right icon Rebased-From: 303bb4d9a8aa5ad9d1d4bb72c83fc92f44247137 Github-Pull: bitcoin-core/gui-qml#119 --- src/qml/bitcoin_qml.qrc | 3 +-- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 +++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/controls/Theme.qml | 28 ------------------------- src/qml/controls/qmldir | 1 - src/qml/doc/icon-policy.md | 2 +- src/qml/imageprovider.cpp | 5 +++++ src/qml/pages/stub.qml | 2 +- src/qml/res/icons/caret-right.png | Bin 0 -> 392 bytes src/qml/res/src/caret-right.svg | 3 +++ 17 files changed, 29 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/Theme.qml delete mode 100644 src/qml/controls/qmldir create mode 100644 src/qml/res/icons/caret-right.png create mode 100644 src/qml/res/src/caret-right.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 50189931c8..0c354852f8 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,16 +10,15 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/qmldir controls/Setting.qml controls/TextButton.qml - controls/Theme.qml pages/initerrormessage.qml pages/stub.qml ../qt/res/icons/bitcoin.png res/icons/caret-left.png + res/icons/caret-right.png res/icons/info.png diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml deleted file mode 100644 index 0542f84120..0000000000 --- a/src/qml/controls/Theme.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -QtObject { - property bool dark: false - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" - } - function toggleDark() { - dark = !dark - } -} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir deleted file mode 100644 index d57fb8673e..0000000000 --- a/src/qml/controls/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Theme 1.0 Theme.qml diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md index a07ba6a12b..2152f0bde6 100644 --- a/src/qml/doc/icon-policy.md +++ b/src/qml/doc/icon-policy.md @@ -17,7 +17,7 @@ PNGs are used in production due to wide application support, transparency suppor and better image quality compared to competing file types such as JPEG. #### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-pngs.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimize-pngs.py) script before their inclusion in Bitcoin Core. +Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. PNG optimization removes various unnecessary color profiles, ancillary data, and text chunks, resulting in a lossless file size reduction. diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 5e03d2df2a..a159387f00 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,6 +32,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/caret-left").pixmap(requested_size); } + if (id == "caret-right") { + *size = requested_size; + return QIcon(":/icons/caret-right").pixmap(requested_size); + } + if (id == "info") { *size = requested_size; return QIcon(":/icons/info").pixmap(requested_size); diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); diff --git a/src/qml/res/icons/caret-right.png b/src/qml/res/icons/caret-right.png new file mode 100644 index 0000000000000000000000000000000000000000..88d1a5489f163e0fbc1a609b6e76e9b8ac8d0ecc GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-F#3DCIEGX(zPYJ7C(Mz-^<(pH z)nEM`Zg;AV%Q@JI0?cIZsmY1R)dQXU5Yb ztSg-O=h`F)H*UM=D`}nkM&+C`m#X=}oLd?5ql#eZ&RX@#slg3}sn6@|JA7n2HukrW35F+?M zAn{!oi-q@;(3({o1vc6Lq`i*bbnBVAXU(kt{X0)?kKZxXc7N;Do&Ea_4*Yv^TR+BU z-`_*L&)Ez1eV+Ti=DGF#pXbW!7$7u6h`nPDMB;SC+&}&N?^4dU&)?ZEpTK8(ay$PA zyK1{Rr{?h&wDNJas`&|LSz6yblmrO~6;G)<3``6+ZWk6tyHBd6P literal 0 HcmV?d00001 diff --git a/src/qml/res/src/caret-right.svg b/src/qml/res/src/caret-right.svg new file mode 100644 index 0000000000..5ec4eefb8b --- /dev/null +++ b/src/qml/res/src/caret-right.svg @@ -0,0 +1,3 @@ + + + From c08ce6d29a0b1189f90bf63bf73a1b538390c116 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 25 May 2022 02:16:01 -0400 Subject: [PATCH 175/979] qml: introduce export icon Rebased-From: 50f979e418416448cd111470d76ac640a04cf81f Github-Pull: bitcoin-core/gui-qml#120 --- src/qml/bitcoin_qml.qrc | 3 +-- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 +++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/controls/Theme.qml | 28 ------------------------- src/qml/controls/qmldir | 1 - src/qml/doc/icon-policy.md | 2 +- src/qml/imageprovider.cpp | 5 +++++ src/qml/pages/stub.qml | 2 +- src/qml/res/icons/export.png | Bin 0 -> 695 bytes src/qml/res/src/export.svg | 5 +++++ 17 files changed, 31 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/Theme.qml delete mode 100644 src/qml/controls/qmldir create mode 100644 src/qml/res/icons/export.png create mode 100644 src/qml/res/src/export.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 19045a7f7c..b3fa64b586 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -10,10 +10,8 @@ controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml - controls/qmldir controls/Setting.qml controls/TextButton.qml - controls/Theme.qml pages/initerrormessage.qml pages/stub.qml @@ -21,6 +19,7 @@ ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png + res/icons/export.png res/icons/info.png diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml deleted file mode 100644 index 0542f84120..0000000000 --- a/src/qml/controls/Theme.qml +++ /dev/null @@ -1,28 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -QtObject { - property bool dark: false - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" - } - function toggleDark() { - dark = !dark - } -} diff --git a/src/qml/controls/qmldir b/src/qml/controls/qmldir deleted file mode 100644 index d57fb8673e..0000000000 --- a/src/qml/controls/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton Theme 1.0 Theme.qml diff --git a/src/qml/doc/icon-policy.md b/src/qml/doc/icon-policy.md index a07ba6a12b..2152f0bde6 100644 --- a/src/qml/doc/icon-policy.md +++ b/src/qml/doc/icon-policy.md @@ -17,7 +17,7 @@ PNGs are used in production due to wide application support, transparency suppor and better image quality compared to competing file types such as JPEG. #### Optimizing Production Files (PNG) -Production (PNG) files must be processed by the [optimize-pngs.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimize-pngs.py) script before their inclusion in Bitcoin Core. +Production (PNG) files must be processed by the [optimize-png.py](https://github.com/bitcoin-core/bitcoin-maintainer-tools/blob/master/optimise-pngs.py) script before their inclusion in Bitcoin Core. PNG optimization removes various unnecessary color profiles, ancillary data, and text chunks, resulting in a lossless file size reduction. diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index a159387f00..0bf54187ac 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -37,6 +37,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/caret-right").pixmap(requested_size); } + if (id == "export") { + *size = requested_size; + return QIcon(":/icons/export").pixmap(requested_size); + } + if (id == "info") { *size = requested_size; return QIcon(":/icons/info").pixmap(requested_size); diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); diff --git a/src/qml/res/icons/export.png b/src/qml/res/icons/export.png new file mode 100644 index 0000000000000000000000000000000000000000..636e8221b35e02505446d82b3b98dad677c713ee GIT binary patch literal 695 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fx7dwIEGX(zP-ZSBNxqZ^yB|m zKU<|g&n#`0a?I5(3!0sndpxuG*0#58TXT2MZL_|bVp+W}zpBnWYx?v0d@*Ax%QmhkokcT*|Xx{{1PerxbO#oY?ij62W#d7jNY<*|&TPddvJpu_^b{;!`)8S9>w<$ON=%syT| zVS3#@BZuI>kFT>utlVFl+8|%C3`72v3^5(HRgx8R>DsXB}(sege zd!B%pUkt+Bru&7yb4(IRP>yt+H@|@)Uo-s3@%a-NW_O#~GcvLXtUAhlsDICbz%P&e z{TldM`rOa+=i6s8-V&~w^8c;6zC*kd_viWZ_b|NXe7b2uyUfBgpu)I@>wg@#eE23T zt&m_T`SZMgQA0x_kSc3vFiiQl(#=N2qpIP9%mTZ_mi;r&MmHT{>#!(~IIT0S(CE+p zFPsV%d=D6KB83ZHG6{A`TaPd4x zv-W4pm$b-i<9uenj7L*>dhAl0|9o3LH18XAhA%a%x86Uo>0bg{c+$LoQ&LUTT2nt* on`R21UU~li9|yyk$Y3wKE^qfDmQeY*zy!(Q>FVdQ&MBb@03@+G*8l(j literal 0 HcmV?d00001 diff --git a/src/qml/res/src/export.svg b/src/qml/res/src/export.svg new file mode 100644 index 0000000000..6bcb7e4a94 --- /dev/null +++ b/src/qml/res/src/export.svg @@ -0,0 +1,5 @@ + + + + + From c98e04e42408e4df781dfc211ec4866d21a81b82 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:05:53 +0200 Subject: [PATCH 176/979] Revert "qml: update UI elements to use Theme color definitions" This reverts commit 07fa49e8d0d80d8c5a50767a6ea258be159d7eef. Rebased-From: b1a73db192779a4ce4767680b8620027f9c3a1c3 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/components/BlockCounter.qml | 5 ++--- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 ++++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/pages/stub.qml | 2 +- 10 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index cf8cc79d22..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,14 +6,13 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: Theme.color.background + color: "black" } - color: Theme.color.orange + color: "orange" padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..9f42e92bdf 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: Theme.color.white + color: "white" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: Theme.color.orange + color: "#F7931A" radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..20dc80b3ac 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: Theme.color.neutral8 + color: "#DEDEDE" text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: Theme.color.neutral9 + color: "#FFFFFF" text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 + border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: Theme.color.orange + border.color: "#F7931A" radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: Theme.color.neutral9 + color: "white" radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: Theme.color.neutral0 + color: "black" text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..3e71039fdf 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? Theme.color.orange : Theme.color.neutral4 + color: root.checked ? "#F7931A" : "#DDDDDD" Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: Theme.color.white + color: "#ffffff" } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 751d251d94..29e2ac49c0 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: Theme.color.neutral9 + color: "white" opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 117a4baebb..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: Theme.color.neutral3 + color: "#404040" Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: Theme.color.orange + color: "orange" } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..d0b97f68d5 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: Theme.color.neutral5 + color: "#777777" } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..bc15172f2b 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: Theme.color.neutral9 + property string textColor: "white" font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: Theme.color.background + color: "black" visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); From e57b4e02713abdf5279d6c84039951c5d9462f6f Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:01 +0200 Subject: [PATCH 177/979] Revert "qml: Used verificationProgress in stub.qml" This reverts commit c1085593bce479a7e4ba62d73d7f706447c0c8fe. Rebased-From: b420a7da790939208cbb1f0334bf766d97861b14 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,7 +47,10 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: nodeModel.verificationProgress + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } } ConnectionOptions { Layout.preferredWidth: 400 From 76245da819578fe924e9597571e5144052b115c4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:08 +0200 Subject: [PATCH 178/979] Revert "qml: demo Header control" This reverts commit d096415f501c1e4266d78853d8c9328bf0a9aeb6. Rebased-From: c60866cda04e3d40b3ee7bfd176b45b394500128 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..a3f36376d9 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -28,18 +28,6 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 0 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 25 - } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From 8ecabeb4c2d1d536420b12c74d7004cdcc8d1908 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:15 +0200 Subject: [PATCH 179/979] Revert "scripted-diff: Bump Qt Quick module versions" This reverts commit 10d4e6c859066add4c05b3ac7ba3889c36831450. Rebased-From: dd47039fc977fa0bd62f84b23e5c95305868bd88 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/components/BlockCounter.qml | 4 ++-- src/qml/components/ConnectionOptions.qml | 6 +++--- src/qml/controls/OptionButton.qml | 6 +++--- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/pages/initerrormessage.qml | 4 ++-- src/qml/pages/stub.qml | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..daefc91e52 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 21a3d3079d..b8ad56fa1c 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../controls" ColumnLayout { diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index e6f83202fe..9d0d851d8d 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..c58f402738 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index 109e51c1a0..e9d4ed8cb0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a3f36376d9..d7c6fdbdfa 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 import "../components" import "../controls" From 80878bc6afd4dcfa50fe0f8541b5912d1cd03a9a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:23 +0200 Subject: [PATCH 180/979] Revert "qml: Demo ProgressIndicator control" This reverts commit d51201f316f9580b9015da6bf38659f35bb5e57e. Rebased-From: ed06305fec85bb084411e5a11ef9ab9307b42124 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d7c6fdbdfa..ff15d7c1b1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,7 +6,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 import "../components" -import "../controls" ApplicationWindow { id: appWindow @@ -32,14 +31,6 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } - } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 17e484e97244d9783a147a7def9090bd2afec2fe Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:37 +0200 Subject: [PATCH 181/979] Revert "qml: Show ConnectionOptions" This reverts commit 2f52214ef6ad867328b35b37d9412201bcae4ed7. Rebased-From: 2668eff27a9663e555ecfe5fcc53783841834b63 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index ff15d7c1b1..06b9f408c7 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,9 +31,5 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } } } From dbdd79388def4b97c35a253bee5011c5f32e9cf7 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:49 +0200 Subject: [PATCH 182/979] Revert "qml: Use ColumnLayout in application window" This reverts commit c34921f967d96e05613b712a15654febe5f1fc05. Rebased-From: 23609ef78aca0502f29b78700fa946fd7a1d7c1f Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 06b9f408c7..35a864ae62 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,19 +17,17 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - ColumnLayout { + Image { + id: appLogo + anchors.horizontalCenter: parent.horizontalCenter + source: "image://images/app" + sourceSize.width: 128 + sourceSize.height: 128 + } + + BlockCounter { + id: blockCounter anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } + blockHeight: nodeModel.blockTipHeight } } From e7c234f500bfa0423108bccbbbf28e40eaeddaf0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:06:58 +0200 Subject: [PATCH 183/979] Revert "qml: Drop import qualifier BitcoinCoreComponents" This reverts commit 6b933f64d0850ad95e95ac04b2fea04cb4684f5a. Rebased-From: 737cb7ca669c7cb506edf511390f445980b04a5b Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 35a864ae62..3b121aa8a1 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,7 +5,8 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import "../components" +import "../components" as BitcoinCoreComponents + ApplicationWindow { id: appWindow @@ -25,7 +26,7 @@ ApplicationWindow { sourceSize.height: 128 } - BlockCounter { + BitcoinCoreComponents.BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From dd576a3dd420b622baf387e0b3a83d9f2f55d773 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:07:07 +0200 Subject: [PATCH 184/979] Revert "doc: Drop unneeded runtime dependencies" This reverts commit 462b4e3b95ae6c828ed530eb1bd94f3eec00e7bb. Rebased-From: d99a5b2aa68d7032055ece3fc9edfaa6748e53c2 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..03534e7cd9 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 ``` #### Fedora: From e7ec080b2e6c63b5e0b3db4cf4670a81f6e80c89 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:07:15 +0200 Subject: [PATCH 185/979] Revert "multiprocess: add new bitcoin-qt init implementation to qml-gui" This reverts commit aed9eb4535a64aeec10d4817c235b67ccb8d0f69. Rebased-From: dccd6d8b40fcfe552d657b70c768bfa0f4696e50 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4cea873af2..1982f5e1a2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -103,12 +104,15 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); + NodeContext node_context; + int unused_exit_status; + std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. + node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 327b34254895035a8d0fbd586502b116ef4a84c4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:09:50 +0200 Subject: [PATCH 186/979] Revert "qml: Set tab focus behavior" This reverts commit 4cff360be10b506b64296f57f9898ecef1563f4d. Rebased-From: 556c4f16658485c9afac505b880eab6d21a68511 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 1982f5e1a2..9ce622ba07 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE @@ -99,7 +98,6 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 912fadc3ba8e3b7aedf7d16a6146afec65472e01 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:09:58 +0200 Subject: [PATCH 187/979] Revert "qml: Drop erroneous `#include `" This reverts commit c677da882f39beb52a0de428ba9b2fb7d749d3a3. Rebased-From: 0107368ab1bdb47893f50539fbb623b01f26d0dd Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9ce622ba07..73406c652d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE From ae81c81ac0e0dd7c15196efedb9dced5583a0fbf Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:10:29 +0200 Subject: [PATCH 188/979] Revert "qml, doc: Add import QtQuick.Layouts" This reverts commit 1e9a195925d6b643095b9cdca9ee5729b7addb2e. Rebased-From: f1b624f573a1709b401317ca6497d4a3b3721ef8 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/README.md | 2 +- src/qml/bitcoin.cpp | 1 - src/qml/pages/stub.qml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qml/README.md b/src/qml/README.md index 03534e7cd9..21aa7ea417 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 ``` #### Fedora: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 73406c652d..a281d04306 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -47,7 +47,6 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); Q_IMPORT_PLUGIN(QtQuickControls2Plugin); Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 3b121aa8a1..7a56f6ce3a 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,7 +4,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 import "../components" as BitcoinCoreComponents From 30f99a370baaf4f7dfe771e26def1c11767b0b53 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:10:43 +0200 Subject: [PATCH 189/979] Revert "qml: Add qInstallMessageHandler" This reverts commit f3e66807740e2a2c07827995ae3c8296cb309e88. Rebased-From: 7aa5302c28311f348407744410e32462ccb410b2 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index a281d04306..7f5a21b99e 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -33,14 +32,9 @@ #include #include #include -#include #include #include -QT_BEGIN_NAMESPACE -class QMessageLogContext; -QT_END_NAMESPACE - #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQmlPlugin) @@ -74,17 +68,6 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } - -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); - } -} } // namespace @@ -195,9 +178,6 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - // Install qDebug() message handler to route to debug.log - qInstallMessageHandler(DebugMessageHandler); - qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); node_model.startShutdownPolling(); From d3fa32e01c1d5d2190bad70e1b30aaa87a964d91 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:11:16 +0200 Subject: [PATCH 190/979] Revert "build, qml: Add qtquickcontrols2 module" This reverts commit 2b482f005893d112428a4db12db3dd72dfe8a359. Rebased-From: 412346afb93305cf66f92654bd3549bdd5b982ec Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 7f5a21b99e..85a498015d 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -41,8 +41,6 @@ Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -Q_IMPORT_PLUGIN(QtQuickControls2Plugin); -Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); #endif namespace { From 57d82bc620eee9ca8f1bae22527464d321ec9f40 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 26 May 2022 20:11:31 +0200 Subject: [PATCH 191/979] Revert "build, qml: Add qtdeclarative module" This reverts commit 0d6c0cbdc69459dc7f1299a00cfa8750250e7470. Rebased-From: e6dee727e34e40e6e291bc92f28118f5ccca8326 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 85a498015d..258f73f01f 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,14 +35,6 @@ #include #include -#if defined(QT_STATICPLUGIN) -#include -Q_IMPORT_PLUGIN(QtQmlPlugin) -Q_IMPORT_PLUGIN(QtQmlModelsPlugin) -Q_IMPORT_PLUGIN(QtQuick2Plugin) -Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) -#endif - namespace { void SetupUIArgs(ArgsManager& argsman) { From 8af93e14b2108f84119126f6b53bd0b74cd62189 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 May 2022 01:46:37 +0200 Subject: [PATCH 192/979] qml: Import static plugins Rebased-From: 46af006befa90d752419712fe5e19250d00a22df Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 258f73f01f..6b71ed54cf 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -35,6 +35,17 @@ #include #include +#if defined(QT_STATICPLUGIN) +#include +Q_IMPORT_PLUGIN(QtQmlPlugin) +Q_IMPORT_PLUGIN(QtQmlModelsPlugin) +Q_IMPORT_PLUGIN(QtQuick2Plugin) +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin); +Q_IMPORT_PLUGIN(QtQuickControls2Plugin); +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin); +#endif + namespace { void SetupUIArgs(ArgsManager& argsman) { From 0a3b03492f0c631476bbbad12ae04a8fe2e39759 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 May 2022 01:51:50 +0200 Subject: [PATCH 193/979] doc, qml: Update runtime dependencies Rebased-From: d51ac6c4971e2b731ef822a1ae93cbabec650abf Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 21aa7ea417..6fae9f9194 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -66,7 +66,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-window2 +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 ``` #### Fedora: From 120287bcfc9458f3989a561cffc0e6b9ec67d82a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 27 May 2022 01:53:51 +0200 Subject: [PATCH 194/979] qml: Add import QtQuick.Layouts Rebased-From: ae5a391420d18d910ec07c9022f0427b2e290ea3 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 7a56f6ce3a..db5ceec3e3 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -4,6 +4,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.15 import "../components" as BitcoinCoreComponents From 867d31b07a21dea9839633fb51594cd7307df3de Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 2 Oct 2021 22:13:33 +0300 Subject: [PATCH 195/979] qml: Add qInstallMessageHandler Rebased-From: d0a2ce6ae49fb7af024c90ab659ee514c3d3df8c Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 6b71ed54cf..9ce622ba07 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,13 @@ #include #include #include -#include +#include #include +QT_BEGIN_NAMESPACE +class QMessageLogContext; +QT_END_NAMESPACE + #if defined(QT_STATICPLUGIN) #include Q_IMPORT_PLUGIN(QtQmlPlugin) @@ -69,6 +74,17 @@ bool InitErrorMessageBox( qGuiApp->exec(); return false; } + +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } +} } // namespace @@ -179,6 +195,9 @@ int QmlGuiMain(int argc, char* argv[]) return EXIT_FAILURE; } + // Install qDebug() message handler to route to debug.log + qInstallMessageHandler(DebugMessageHandler); + qInfo() << "Graphics API in use:" << QmlUtil::GraphicsApi(window); node_model.startShutdownPolling(); From 409d7901316f4a77b705c7164c75251212b08f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:20:03 +0100 Subject: [PATCH 196/979] qml: Set tab focus behavior Rebased-From: 8eba0716b662ebb4b084e62e6757c47fb5e0b569 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 9ce622ba07..1982f5e1a2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -98,6 +99,7 @@ int QmlGuiMain(int argc, char* argv[]) Q_INIT_RESOURCE(bitcoin_qml); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); QGuiApplication app(argc, argv); auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); From 98593f79fbe44deeae053df458df1a6cf14dce53 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 27 Oct 2021 14:49:32 -0400 Subject: [PATCH 197/979] multiprocess: add new bitcoin-qt init implementation to qml-gui This incorporates the new bitcoin-qt init implementation into the qml-gui. Rebased-From: b69bc2936ddf8cc23748ca1a4bf19ec529a0d699 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/bitcoin.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 1982f5e1a2..4cea873af2 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -104,15 +103,12 @@ int QmlGuiMain(int argc, char* argv[]) auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(InitErrorMessageBox); - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); /// Parse command-line options. We do this after qt in order to show an error if there are problems parsing these. - node_context.args = &gArgs; SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; From 6886cc4a7b98c8f7bda78d53af42aa11de0a5bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 21 Oct 2021 23:10:14 +0100 Subject: [PATCH 198/979] qml: Drop import qualifier BitcoinCoreComponents Rebased-From: 64e61541ecf14e6cde8c2dc70cf09c96373ad1f0 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index db5ceec3e3..a6276c08bb 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -5,8 +5,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.15 -import "../components" as BitcoinCoreComponents - +import "../components" ApplicationWindow { id: appWindow @@ -26,7 +25,7 @@ ApplicationWindow { sourceSize.height: 128 } - BitcoinCoreComponents.BlockCounter { + BlockCounter { id: blockCounter anchors.centerIn: parent blockHeight: nodeModel.blockTipHeight From c385960c06a72d6b59ec8aeaa4895010c85952a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:44:47 +0100 Subject: [PATCH 199/979] qml: Use ColumnLayout in application window Rebased-From: 18db2862813b32bdf5cf6e3a0a2f8754c9a90571 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a6276c08bb..b659b79d43 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -17,17 +17,19 @@ ApplicationWindow { Component.onCompleted: nodeModel.startNodeInitializionThread(); - Image { - id: appLogo - anchors.horizontalCenter: parent.horizontalCenter - source: "image://images/app" - sourceSize.width: 128 - sourceSize.height: 128 - } - - BlockCounter { - id: blockCounter + ColumnLayout { anchors.centerIn: parent - blockHeight: nodeModel.blockTipHeight + spacing: 15 + width: 400 + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } } } From 4fcbe11f339b6a07a07af2b05cb250d4215b74a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:46:48 +0100 Subject: [PATCH 200/979] qml: Show ConnectionOptions Rebased-From: 34e2ee168c03c03c5f12b479ed67e3c3c888f5aa Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index b659b79d43..d1b9408ff4 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -31,5 +31,9 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ConnectionOptions { + Layout.preferredWidth: 400 + focus: true + } } } From 6335e47ea31c97e22dd4824014a6c6acdf7b1a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Fri, 22 Oct 2021 22:48:06 +0100 Subject: [PATCH 201/979] qml: Demo ProgressIndicator control Rebased-From: 915ed0e9e8065062f762248051e064da1e16bc02 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index d1b9408ff4..9547be2e92 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -6,6 +6,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.15 import "../components" +import "../controls" ApplicationWindow { id: appWindow @@ -31,6 +32,14 @@ ApplicationWindow { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight } + ProgressIndicator { + id: indicator + Layout.fillWidth: true + progress: 0.666 + background: MouseArea { + onClicked: indicator.progress = mouseX / width + } + } ConnectionOptions { Layout.preferredWidth: 400 focus: true From 8e46b0d15886466694b7c932b16c4da68417ea78 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 24 Dec 2021 12:04:23 +0200 Subject: [PATCH 202/979] scripted-diff: Bump Qt Quick module versions -BEGIN VERIFY SCRIPT- QML_FILES=$(git ls-files '*.qml') sed -i -e 's/import QtQuick 2.12/import QtQuick 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Controls 2.12/import QtQuick.Controls 2.15/' -- $QML_FILES sed -i -e 's/import QtQuick.Layouts 1.11/import QtQuick.Layouts 1.15/' -- $QML_FILES -END VERIFY SCRIPT- Rebased-From: a32fa3092f2e8a1aa428482a97b049ffc3001899 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/components/BlockCounter.qml | 4 ++-- src/qml/components/ConnectionOptions.qml | 6 +++--- src/qml/controls/OptionButton.qml | 6 +++--- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/pages/initerrormessage.qml | 4 ++-- src/qml/pages/stub.qml | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index daefc91e52..840c790f17 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -4,8 +4,8 @@ // The BlockCounter component. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Label { property int blockHeight: 0 diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index b8ad56fa1c..21a3d3079d 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import "../controls" ColumnLayout { diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 9d0d851d8d..e6f83202fe 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -2,9 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.11 +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 Button { property string description diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index c58f402738..8231f1967f 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 Control { property real progress: 0 diff --git a/src/qml/pages/initerrormessage.qml b/src/qml/pages/initerrormessage.qml index e9d4ed8cb0..109e51c1a0 100644 --- a/src/qml/pages/initerrormessage.qml +++ b/src/qml/pages/initerrormessage.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 ApplicationWindow { title: "Bitcoin Core TnG" diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 9547be2e92..a3f36376d9 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -import QtQuick 2.12 -import QtQuick.Controls 2.12 +import QtQuick 2.15 +import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import "../components" import "../controls" From f7df428d21b7cb5df8531b2089aefddc3e8b1d7d Mon Sep 17 00:00:00 2001 From: jarolrod Date: Sun, 2 Jan 2022 22:59:24 -0500 Subject: [PATCH 203/979] qml: demo Header control Rebased-From: 61380a54cce61fb371c60ead02d43006c4cdafba Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index a3f36376d9..f8937def52 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -28,6 +28,18 @@ ApplicationWindow { sourceSize.width: 64 sourceSize.height: 64 } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 0 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 25 + } BlockCounter { Layout.alignment: Qt.AlignCenter blockHeight: nodeModel.blockTipHeight From cfae61d0301ba86fbebc85ceb3fb603b730f6755 Mon Sep 17 00:00:00 2001 From: Shashwat Date: Thu, 6 Jan 2022 20:00:11 +0530 Subject: [PATCH 204/979] qml: Used verificationProgress in stub.qml - This commit uses the function added in previous commit to display the working progress bar in GUI - This commit also removes the tempory mouseClick event which used to change the progress meter when clicked. Rebased-From: 328bf76f4b129f4b3c5252734dcb06e1a8f815a6 Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/pages/stub.qml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index f8937def52..bd21db77de 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -47,10 +47,7 @@ ApplicationWindow { ProgressIndicator { id: indicator Layout.fillWidth: true - progress: 0.666 - background: MouseArea { - onClicked: indicator.progress = mouseX / width - } + progress: nodeModel.verificationProgress } ConnectionOptions { Layout.preferredWidth: 400 From debdf5ef1b1a785e49f3b384496b3ee04ab03499 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Thu, 6 Jan 2022 16:00:19 -0500 Subject: [PATCH 205/979] qml: update UI elements to use Theme color definitions Rebased-From: dbcd29aac063a7b51309e0e54a0f6ce02b8d64ab Github-Pull: bitcoin-core/gui-qml#121 --- src/qml/components/BlockCounter.qml | 5 +++-- src/qml/controls/ContinueButton.qml | 4 ++-- src/qml/controls/Header.qml | 6 +++--- src/qml/controls/OptionButton.qml | 8 ++++---- src/qml/controls/OptionSwitch.qml | 4 ++-- src/qml/controls/PageIndicator.qml | 2 +- src/qml/controls/ProgressIndicator.qml | 4 ++-- src/qml/controls/Setting.qml | 2 +- src/qml/controls/TextButton.qml | 2 +- src/qml/pages/stub.qml | 2 +- 10 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/qml/components/BlockCounter.qml b/src/qml/components/BlockCounter.qml index 840c790f17..cf8cc79d22 100644 --- a/src/qml/components/BlockCounter.qml +++ b/src/qml/components/BlockCounter.qml @@ -6,13 +6,14 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 +import "../controls" Label { property int blockHeight: 0 background: Rectangle { - color: "black" + color: Theme.color.background } - color: "orange" + color: Theme.color.orange padding: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 9f42e92bdf..2b98f8baff 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -12,14 +12,14 @@ Button { contentItem: Text { text: parent.text font: parent.font - color: "white" + color: Theme.color.white horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { implicitHeight: 46 implicitWidth: 300 - color: "#F7931A" + color: Theme.color.orange radius: 5 } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 20dc80b3ac..13d42e1c43 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -28,7 +28,7 @@ Control { font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" font.pointSize: root.headerSize - color: "#FFFFFF" + color: Theme.color.neutral9 text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -43,7 +43,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pointSize: root.descriptionSize - color: "#DEDEDE" + color: Theme.color.neutral8 text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap @@ -59,7 +59,7 @@ Control { font.family: "Inter" font.styleName: "Regular" font.pixelSize: root.subtextSize - color: "#FFFFFF" + color: Theme.color.neutral9 text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft wrapMode: Text.WordWrap diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index e6f83202fe..56d07cb407 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -15,7 +15,7 @@ Button { property alias detail: detail_loader.sourceComponent background: Rectangle { border.width: 1 - border.color: button.checked ? "#F7931A" : button.hovered ? "white" : "#999999" + border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 radius: 10 color: "transparent" Rectangle { @@ -23,7 +23,7 @@ Button { anchors.fill: parent anchors.margins: -4 border.width: 2 - border.color: "#F7931A" + border.color: Theme.color.orange radius: 14 color: "transparent" opacity: 0.4 @@ -50,7 +50,7 @@ Button { visible: active sourceComponent: Label { background: Rectangle { - color: "white" + color: Theme.color.neutral9 radius: 3 } font.styleName: "Regular" @@ -59,7 +59,7 @@ Button { rightPadding: 7 bottomPadding: 4 leftPadding: 7 - color: "black" + color: Theme.color.neutral0 text: qsTr("Recommended") } } diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index 3e71039fdf..b54660c276 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -13,7 +13,7 @@ Switch { x: root.leftPadding y: Math.round((parent.height - height) / 2) radius: 18 - color: root.checked ? "#F7931A" : "#DDDDDD" + color: root.checked ? Theme.color.orange : Theme.color.neutral4 Rectangle { id: indicatorButton y: parent.height / 2 - height / 2 @@ -21,7 +21,7 @@ Switch { width: 20 height: 20 radius: 18 - color: "#ffffff" + color: Theme.color.white } } } diff --git a/src/qml/controls/PageIndicator.qml b/src/qml/controls/PageIndicator.qml index 29e2ac49c0..751d251d94 100644 --- a/src/qml/controls/PageIndicator.qml +++ b/src/qml/controls/PageIndicator.qml @@ -11,7 +11,7 @@ PageIndicator { implicitWidth: 10 implicitHeight: 10 radius: Math.round(width / 2) - color: "white" + color: Theme.color.neutral9 opacity: index === root.currentIndex ? 0.95 : pressed ? 0.7 : 0.45 Behavior on opacity { OpacityAnimator { diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml index 8231f1967f..117a4baebb 100644 --- a/src/qml/controls/ProgressIndicator.qml +++ b/src/qml/controls/ProgressIndicator.qml @@ -17,7 +17,7 @@ Control { contentItem: Rectangle { implicitHeight: 6 radius: Math.floor(height / 2) - color: "#404040" + color: Theme.color.neutral3 Item { width: Math.round(progress * contentItem.width) height: parent.height @@ -26,7 +26,7 @@ Control { width: contentItem.width height: contentItem.height radius: contentItem.radius - color: "orange" + color: Theme.color.orange } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index d0b97f68d5..52dc1f706d 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -35,7 +35,7 @@ Control { visible: active sourceComponent: Rectangle { height: 1 - color: "#777777" + color: Theme.color.neutral5 } } } diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index bc15172f2b..1063a275ba 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { id: root property int textSize: 18 - property string textColor: "white" + property string textColor: Theme.color.neutral9 font.family: "Inter" font.styleName: "Semi Bold" font.pointSize: root.textSize diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index bd21db77de..61baf5e2cf 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -13,7 +13,7 @@ ApplicationWindow { title: "Bitcoin Core TnG" minimumWidth: 750 minimumHeight: 450 - color: "black" + color: Theme.color.background visible: true Component.onCompleted: nodeModel.startNodeInitializionThread(); From f3e6d4be1d69b8d19451f65f63919eb75021e58d Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 28 May 2022 12:39:05 +0200 Subject: [PATCH 206/979] qml, refactor: Move `interfaces::BlockAndHeaderTipInfo` registration This change is required for easier syncing with the main repo, and it partially reverts commit 3ab3c87f3c1955e882ee5d0e1076e0c8ecc532dd. Rebased-From: 905f9ab408696d36a1b208b3f9185311fd0aec40 Github-Pull: bitcoin-core/gui-qml#122 --- src/qml/bitcoin.cpp | 1 + src/qml/bitcoin_qml.qrc | 1 - src/qml/controls/Wizard.qml | 51 ------------------------------------- 3 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 src/qml/controls/Wizard.qml diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 4cea873af2..873c59b26a 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -96,6 +96,7 @@ int QmlGuiMain(int argc, char* argv[]) #endif // WIN32 Q_INIT_RESOURCE(bitcoin_qml); + qRegisterMetaType("interfaces::BlockAndHeaderTipInfo"); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls); diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 8f27ce3433..bd07aa92a3 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -14,7 +14,6 @@ controls/Setting.qml controls/TextButton.qml controls/Theme.qml - controls/Wizard.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/Wizard.qml b/src/qml/controls/Wizard.qml deleted file mode 100644 index 97bbf9369f..0000000000 --- a/src/qml/controls/Wizard.qml +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Page { - id: root - property var views - property alias finished: swipeView.finished - background: null - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: swipeView.currentIndex > 0 ? true : false - visible: active - sourceComponent: TextButton { - text: "‹ Back" - onClicked: swipeView.currentIndex -= 1 - } - } - } - SwipeView { - id: swipeView - property bool inSubPage: false - property bool finished: false - anchors.fill: parent - interactive: false - Repeater { - model: views.length - Loader { - source: "../pages/" + views[index] - } - } - } - footer: Page { - background: Rectangle { - color: "black" - } - contentItem: RowLayout { - PageIndicator { - Layout.alignment: Qt.AlignCenter - count: swipeView.count - currentIndex: swipeView.currentIndex - } - } - } -} From da5741c3a297e2e5ec1f1ae79c7a4bbe50465cd0 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Tue, 4 Jan 2022 14:40:03 -0500 Subject: [PATCH 207/979] qml: introduce Wizard control Rebased-From: dffb73e6824a0d0dac378208a5b27889fc225b14 Github-Pull: bitcoin-core/gui-qml#106 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/Wizard.qml | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/qml/controls/Wizard.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index bd07aa92a3..8f27ce3433 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -14,6 +14,7 @@ controls/Setting.qml controls/TextButton.qml controls/Theme.qml + controls/Wizard.qml pages/initerrormessage.qml pages/stub.qml diff --git a/src/qml/controls/Wizard.qml b/src/qml/controls/Wizard.qml new file mode 100644 index 0000000000..97bbf9369f --- /dev/null +++ b/src/qml/controls/Wizard.qml @@ -0,0 +1,51 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Page { + id: root + property var views + property alias finished: swipeView.finished + background: null + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: swipeView.currentIndex > 0 ? true : false + visible: active + sourceComponent: TextButton { + text: "‹ Back" + onClicked: swipeView.currentIndex -= 1 + } + } + } + SwipeView { + id: swipeView + property bool inSubPage: false + property bool finished: false + anchors.fill: parent + interactive: false + Repeater { + model: views.length + Loader { + source: "../pages/" + views[index] + } + } + } + footer: Page { + background: Rectangle { + color: "black" + } + contentItem: RowLayout { + PageIndicator { + Layout.alignment: Qt.AlignCenter + count: swipeView.count + currentIndex: swipeView.currentIndex + } + } + } +} From 36358ab74b51de63e74826b64e8c2b19bdefe901 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Fri, 1 Jul 2022 00:19:34 -0400 Subject: [PATCH 208/979] doc: add arm macOS CI artifact link, document codesign step Adds a link to the arm macOS CI artifact to the qml readme. Additionally, documents that signing the binary is a requirement before one can run it. Also provides an example command on how one could sign the artifact. Rebased-From: 285afb6ac4705b3e8e3207c5cd61a72f9a1329fb Github-Pull: bitcoin-core/gui-qml#134 --- src/qml/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index 6fae9f9194..cdfc749dab 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -6,9 +6,17 @@ This directory contains the source code for an experimental Bitcoin Core graphic Insecure CI artifacts are available for local testing of the master branch, avoiding the need to build: - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) -- for macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Intel macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) +- for Apple Silicon macOS: [`insecure_mac_arm64_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos_arm64/insecure_mac_arm64_gui.zip) - for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) +Note: For Apple Silicon macOS machines, the binary must be signed before it can +be ran. To apply a signature, run the following on the unzipped CI artifact: + +``` +codesign -s - ./Downloads/insecure_mac_arm64_gui +``` + ## Goals and Limitations The current Bitcoin Core GUI has gathered enough technical debt and hacked on features; it is time to begin anew. From b5b3685aac9a0794e652deafb09fdb549ec612ad Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 6 Jul 2022 00:26:01 -0400 Subject: [PATCH 209/979] doc: document Android CI artifact architecture Rebased-From: 3d1312c175a24e9aeb1ce67fee5b71496aa27798 Github-Pull: bitcoin-core/gui-qml#136 --- src/qml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/README.md b/src/qml/README.md index cdfc749dab..afde37dd0f 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -8,7 +8,7 @@ Insecure CI artifacts are available for local testing of the master branch, avoi - for Windows: [`insecure_win_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip) - for Intel macOS: [`insecure_mac_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip) - for Apple Silicon macOS: [`insecure_mac_arm64_gui.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos_arm64/insecure_mac_arm64_gui.zip) -- for Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) +- for ARM64 Android: [`insecure_android_apk.zip`](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip) Note: For Apple Silicon macOS machines, the binary must be signed before it can be ran. To apply a signature, run the following on the unzipped CI artifact: From 840029fc74b582718bddf1bfd795cca19f468781 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 9 Jul 2022 17:19:13 +0100 Subject: [PATCH 210/979] qml: Avoid incompatibility with CMake AUTOUIC feature See the 018d70b58726b361b6951e0e6de04f13eb97a89d commit in the main repository. Rebased-From: 70591bf2ad59a4e6355ed130b82051ea0914f149 Github-Pull: bitcoin-core/gui-qml#137 --- src/qml/bitcoin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 873c59b26a..c2475e13d8 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include From deb03f71417055f9744f8b3e030d6c5ba788f90d Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 5 Jun 2022 20:26:59 -0400 Subject: [PATCH 211/979] qml: Changes to Wizard Control - Removed Page Indicator from Wizard Control - This is no longer supposed to be a part of the wizard in consideration of design talks and as specified in the figma design files. - Removed navbar code from Wizard.qml. - Navbar code is later moved on each page seperately. Rebased-From: 79e959c12f3c7ed3e90619f4cf969325f2c46a0b Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/controls/Wizard.qml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/qml/controls/Wizard.qml b/src/qml/controls/Wizard.qml index 97bbf9369f..34bfdc1ab7 100644 --- a/src/qml/controls/Wizard.qml +++ b/src/qml/controls/Wizard.qml @@ -11,18 +11,6 @@ Page { property var views property alias finished: swipeView.finished background: null - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: swipeView.currentIndex > 0 ? true : false - visible: active - sourceComponent: TextButton { - text: "‹ Back" - onClicked: swipeView.currentIndex -= 1 - } - } - } SwipeView { id: swipeView property bool inSubPage: false @@ -36,16 +24,4 @@ Page { } } } - footer: Page { - background: Rectangle { - color: "black" - } - contentItem: RowLayout { - PageIndicator { - Layout.alignment: Qt.AlignCenter - count: swipeView.count - currentIndex: swipeView.currentIndex - } - } - } } From fa2e734761e8c71d17e1c3f1ba85b0080e96b05b Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 02:30:26 +0530 Subject: [PATCH 212/979] qml: Changes to Header.qml TextButton.qml, OptionButton.qml and Settings.qml Changes: - Added option to not wrap the text in Header.qml - Added option to bold the text and right align the text in TextButton.qml - Added implicitWidth: 450 for OptionButton.qml - These changes are the prerequisite to the forthcoming commits. - Fixed OptionSwitch rightMargin used in Settings.qml Rebased-From: 8763690db1af6c3956c4f3fc60a30b445db5a01f Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/controls/ContinueButton.qml | 2 +- src/qml/controls/Header.qml | 11 ++++++----- src/qml/controls/OptionButton.qml | 1 + src/qml/controls/Setting.qml | 1 + src/qml/controls/TextButton.qml | 8 +++++--- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/qml/controls/ContinueButton.qml b/src/qml/controls/ContinueButton.qml index 2b98f8baff..d478ba45e8 100644 --- a/src/qml/controls/ContinueButton.qml +++ b/src/qml/controls/ContinueButton.qml @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15 Button { font.family: "Inter" font.styleName: "Semi Bold" - font.pointSize: 18 + font.pixelSize: 18 contentItem: Text { text: parent.text font: parent.font diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 13d42e1c43..c7adcf3097 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -19,6 +19,7 @@ Control { property string subtext property int subtextMargin property int subtextSize: 15 + property bool wrap: true contentItem: ColumnLayout { spacing: 0 Label { @@ -27,11 +28,11 @@ Control { topPadding: root.headerMargin font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" - font.pointSize: root.headerSize + font.pixelSize: root.headerSize color: Theme.color.neutral9 text: root.header horizontalAlignment: center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap + wrapMode: wrap ? Text.WordWrap : Text.NoWrap } Loader { Layout.fillWidth: true @@ -42,11 +43,11 @@ Control { topPadding: root.descriptionMargin font.family: "Inter" font.styleName: "Regular" - font.pointSize: root.descriptionSize + font.pixelSize: root.descriptionSize color: Theme.color.neutral8 text: root.description horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap + wrapMode: wrap ? Text.WordWrap : Text.NoWrap } } Loader { @@ -62,7 +63,7 @@ Control { color: Theme.color.neutral9 text: root.subtext horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft - wrapMode: Text.WordWrap + wrapMode: wrap ? Text.WordWrap : Text.NoWrap } } } diff --git a/src/qml/controls/OptionButton.qml b/src/qml/controls/OptionButton.qml index 56d07cb407..97485fb1eb 100644 --- a/src/qml/controls/OptionButton.qml +++ b/src/qml/controls/OptionButton.qml @@ -13,6 +13,7 @@ Button { padding: 15 checkable: true property alias detail: detail_loader.sourceComponent + implicitWidth: 450 background: Rectangle { border.width: 1 border.color: button.checked ? Theme.color.orange : button.hovered ? Theme.color.neutral9 : Theme.color.neutral5 diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index 52dc1f706d..b11d6c3ca2 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -26,6 +26,7 @@ Control { } OptionSwitch { Layout.alignment: Qt.AlignRight + Layout.rightMargin: -12 } } Loader { diff --git a/src/qml/controls/TextButton.qml b/src/qml/controls/TextButton.qml index 1063a275ba..757d3a4dee 100644 --- a/src/qml/controls/TextButton.qml +++ b/src/qml/controls/TextButton.qml @@ -9,14 +9,16 @@ Button { id: root property int textSize: 18 property string textColor: Theme.color.neutral9 + property bool bold: true + property bool rightalign: false font.family: "Inter" - font.styleName: "Semi Bold" - font.pointSize: root.textSize + font.styleName: bold ? "Semi Bold" : "Regular" + font.pixelSize: root.textSize contentItem: Text { text: root.text font: root.font color: root.textColor - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: rightalign ? Text.AlignRight : Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: null From 64b8aa6d11102ad2ead1c831397da991c2692a36 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 02:36:32 +0530 Subject: [PATCH 213/979] qml: Add Information.qml in src/qml/controls - This is an object similar to Setting.qml - Instead of a switch button this allows to have the text as the option's value. - The text could also double as an hyperlink if the link is given. - The header text has the property that it could be set to be an editable text. - Adds an optional property to display image instead of descriptive text, which also optionally can have a link attached to it. Rebased-From: a17b84ec675c8ab27a560d9d301c8f8d96d90443 Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/Information.qml | 88 ++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 src/qml/controls/Information.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 8f27ce3433..811cb40db9 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -6,6 +6,7 @@ components/StorageOptions.qml controls/ContinueButton.qml controls/Header.qml + controls/Information.qml controls/PageIndicator.qml controls/OptionButton.qml controls/OptionSwitch.qml diff --git a/src/qml/controls/Information.qml b/src/qml/controls/Information.qml new file mode 100644 index 0000000000..e5bf578fc4 --- /dev/null +++ b/src/qml/controls/Information.qml @@ -0,0 +1,88 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + property bool last: parent && root === parent.children[parent.children.length - 1] + required property string header + property string subtext + property int subtextMargin: 3 + property string description + property int descriptionMargin: 10 + property int descriptionSize: 18 + property bool isReadonly: true + property bool hasIcon: false + property string iconSource + property int iconWidth: 30 + property int iconHeight: 30 + property string link + contentItem: ColumnLayout { + spacing: 20 + width: parent.width + RowLayout { + Header { + Layout.fillWidth: true + center: false + header: root.header + headerSize: 18 + description: root.subtext + descriptionSize: 15 + descriptionMargin: root.subtextMargin + wrap: false + } + Loader { + Layout.fillWidth: true + Layout.preferredWidth: 0 + Layout.alignment: Qt.AlignRight | Qt.AlignHCenter + active: root.description.length > 0 + visible: active + sourceComponent: TextEdit { + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: root.descriptionSize + color: Theme.color.neutral8 + textFormat: Text.RichText + text: "" + "" + root.description + "" + readOnly: isReadonly + onLinkActivated: Qt.openUrlExternally(link) + horizontalAlignment: Text.AlignRight + wrapMode: Text.WordWrap + } + } + Loader { + Layout.preferredWidth: root.iconWidth + Layout.preferredHeight: root.iconHeight + Layout.alignment: Qt.AlignRight | Qt.AlignHCenter + active: root.hasIcon + visible: active + sourceComponent: Image { + horizontalAlignment: Image.AlignRight + source: root.iconSource + fillMode: Image.PreserveAspectFit + mipmap: true + MouseArea { + anchors.fill: parent + onClicked: { + Qt.openUrlExternally(link) + } + } + } + } + } + Loader { + Layout.fillWidth:true + Layout.columnSpan: 2 + active: !last + visible: active + sourceComponent: Rectangle { + height: 1 + color: Theme.color.neutral5 + } + } + } +} From 6d12f84e534393922a7958238c347fa9707acc3d Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 02:48:51 +0530 Subject: [PATCH 214/979] qml: Add onboarding01 and its subpages - Adds the onboarding01.qml file and its 3 subpages - onboarding01a.qml : Introduction - onboarding01b.qml : About - onboarding01c.qml : Developers Options - Adds the AboutOptions and DeveloperOptions component which facilitates working of the pages 01b and 01c respectively. Rebased-From: 3c298fef921b58d2c818cdb7e1b9f50fb97832ab Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 6 ++ src/qml/components/AboutOptions.qml | 65 +++++++++++++++++ src/qml/components/DeveloperOptions.qml | 40 +++++++++++ src/qml/pages/onboarding/onboarding01.qml | 30 ++++++++ src/qml/pages/onboarding/onboarding01a.qml | 82 ++++++++++++++++++++++ src/qml/pages/onboarding/onboarding01b.qml | 70 ++++++++++++++++++ src/qml/pages/onboarding/onboarding01c.qml | 68 ++++++++++++++++++ 7 files changed, 361 insertions(+) create mode 100644 src/qml/components/AboutOptions.qml create mode 100644 src/qml/components/DeveloperOptions.qml create mode 100644 src/qml/pages/onboarding/onboarding01.qml create mode 100644 src/qml/pages/onboarding/onboarding01a.qml create mode 100644 src/qml/pages/onboarding/onboarding01b.qml create mode 100644 src/qml/pages/onboarding/onboarding01c.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 811cb40db9..3cf4ab83ed 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -1,8 +1,10 @@ + components/AboutOptions.qml components/BlockCounter.qml components/ConnectionOptions.qml components/ConnectionSettings.qml + components/DeveloperOptions.qml components/StorageOptions.qml controls/ContinueButton.qml controls/Header.qml @@ -17,6 +19,10 @@ controls/Theme.qml controls/Wizard.qml pages/initerrormessage.qml + pages/onboarding/onboarding01.qml + pages/onboarding/onboarding01a.qml + pages/onboarding/onboarding01b.qml + pages/onboarding/onboarding01c.qml pages/stub.qml diff --git a/src/qml/components/AboutOptions.qml b/src/qml/components/AboutOptions.qml new file mode 100644 index 0000000000..83f5922390 --- /dev/null +++ b/src/qml/components/AboutOptions.qml @@ -0,0 +1,65 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + spacing: 20 + Information { + Layout.fillWidth: true + header: qsTr("Website") + description: qsTr("bitcoincore.org >") + link: "https://bitcoincore.org" + } + Information { + Layout.fillWidth: true + header: qsTr("Source code") + description: qsTr("github.com/bitcoin/bitcoin >") + link: "https://github.com/bitcoin/bitcoin" + } + Information { + Layout.fillWidth: true + header: qsTr("License") + description: qsTr("MIT >") + link: "https://opensource.org/licenses/MIT" + } + Information { + Layout.fillWidth: true + header: qsTr("Version") + description: qsTr("v22.99.0-1e7564eca8a6 >") + link: "https://bitcoin.org/en/download" + } + RowLayout { + Header { + Layout.fillWidth: true + center: false + header: qsTr("Developer options") + headerSize: 18 + description: qsTr("Only use these if you have development experience") + descriptionSize: 15 + descriptionMargin: 10 + wrap: false + } + Loader { + Layout.fillWidth: true + Layout.preferredWidth: 0 + Layout.alignment: Qt.AlignRight + Layout.rightMargin: 5 + active: true + visible: active + sourceComponent: TextButton { + text: ">" + bold: false + rightalign: true + onClicked: { + introductions.incrementCurrentIndex() + swipeView.inSubPage = true + } + } + } + } +} diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml new file mode 100644 index 0000000000..1404168f0e --- /dev/null +++ b/src/qml/components/DeveloperOptions.qml @@ -0,0 +1,40 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + spacing: 20 + Information { + Layout.fillWidth: true + header: qsTr("Developer documentation") + hasIcon: true + iconSource: "qrc:/icons/export" + link: "https://bitcoin.org/en/bitcoin-core/contribute/documentation" + } + Setting { + Layout.fillWidth: true + header: qsTr("Storage limit") + } + Information { + Layout.fillWidth: true + header: qsTr("Network") + description: qsTr("Mainnet") + isReadonly: false + } + Information { + Layout.fillWidth: true + header: qsTr("Other option...") + description: qsTr("42") + isReadonly: false + } + Setting { + Layout.fillWidth: true + header: qsTr("Other option...") + description: qsTr("Description...") + } +} diff --git a/src/qml/pages/onboarding/onboarding01.qml b/src/qml/pages/onboarding/onboarding01.qml new file mode 100644 index 0000000000..d44a41bfdb --- /dev/null +++ b/src/qml/pages/onboarding/onboarding01.qml @@ -0,0 +1,30 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + SwipeView { + id: introductions + anchors.fill: parent + interactive: false + orientation: Qt.Horizontal + Loader { + source:"onboarding01a.qml" + } + Loader { + source:"onboarding01b.qml" + } + Loader { + source:"onboarding01c.qml" + } + } +} diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml new file mode 100644 index 0000000000..784ef0260d --- /dev/null +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -0,0 +1,82 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" + +Page { + background: null + clip: true + Layout.fillWidth: true + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.margins: 11 + sourceComponent: Item { + width: 24 + height: 24 + Rectangle { + anchors.fill: parent + color: Theme.color.white + radius: width*0.5 + } + Image { + id: icon + source: "qrc:/icons/info" + width: parent.width + height: parent.height + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + mipmap: true + MouseArea { + anchors.fill: parent + onClicked: { + introductions.incrementCurrentIndex() + swipeView.inSubPage = true + } + } + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 100 + sourceSize.height: 100 + } + Header { + Layout.fillWidth: true + implicitWidth: childrenRect.width + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 10 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 30 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Start" + onClicked: swipeView.incrementCurrentIndex() + } + } +} diff --git a/src/qml/pages/onboarding/onboarding01b.qml b/src/qml/pages/onboarding/onboarding01b.qml new file mode 100644 index 0000000000..16db8208ee --- /dev/null +++ b/src/qml/pages/onboarding/onboarding01b.qml @@ -0,0 +1,70 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + clip: true + Layout.fillWidth: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = false + } + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: "About" + description: qsTr("Bitcoin Core is an open source project.\nIf you find it useful, please contribute.\n\n This is experimental software.") + descriptionMargin: 20 + } + AboutOptions { + Layout.topMargin: 30 + } + } +} diff --git a/src/qml/pages/onboarding/onboarding01c.qml b/src/qml/pages/onboarding/onboarding01c.qml new file mode 100644 index 0000000000..80ce7adcbb --- /dev/null +++ b/src/qml/pages/onboarding/onboarding01c.qml @@ -0,0 +1,68 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + clip: true + Layout.fillWidth: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = true + } + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: "Developer options" + } + DeveloperOptions { + Layout.topMargin: 30 + } + } +} From 637965afeeefdec3c2217f27859f1780da60f887 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 02:57:44 +0530 Subject: [PATCH 215/979] qml: Add onboarding02.qml file - This corresponds to the second page, which talks about Strengthening Bitcoin Rebased-From: 7db1673eadc211e0a2b8e75047bc2cfca57f7372 Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/pages/onboarding/onboarding02.qml | 77 +++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/qml/pages/onboarding/onboarding02.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 3cf4ab83ed..0d2e942fa2 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -23,6 +23,7 @@ pages/onboarding/onboarding01a.qml pages/onboarding/onboarding01b.qml pages/onboarding/onboarding01c.qml + pages/onboarding/onboarding02.qml pages/stub.qml diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml new file mode 100644 index 0000000000..1628a4ef1b --- /dev/null +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -0,0 +1,77 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" + +Page { + background: null + clip: true + Layout.fillWidth: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 200 + sourceSize.height: 200 + } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Strengthen bitcoin") + headerMargin: 30 + description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } + } +} From 12f61e73cf5fba547459d0973151eeb69d88aaf4 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 03:09:41 +0530 Subject: [PATCH 216/979] qml: Added onboarding03.qml - The page correponds to the block clock page in design file. - The block clock is temporarily replaced with the Bitcoin core app icon Rebased-From: a1bf6582aaa386ece76e324d343f6bf10a56107b Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/pages/onboarding/onboarding03.qml | 77 +++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/qml/pages/onboarding/onboarding03.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 0d2e942fa2..7491992279 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -24,6 +24,7 @@ pages/onboarding/onboarding01b.qml pages/onboarding/onboarding01c.qml pages/onboarding/onboarding02.qml + pages/onboarding/onboarding03.qml pages/stub.qml diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml new file mode 100644 index 0000000000..5b127f9bd9 --- /dev/null +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -0,0 +1,77 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" + +Page { + background: null + clip: true + Layout.fillWidth: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 200 + sourceSize.height: 200 + } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("The block clock") + headerMargin: 30 + description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } + } +} From 61dcd46c7fee4489e010135c6fb74f9b8ae5d662 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 03:34:09 +0530 Subject: [PATCH 217/979] qml: Add onboarding04.qml page - This page corresponds to the "Storage location" page in design file. - This commit also adds a component file: StorageLocations.qml to facilitate the working of the onboarding04.qml file. Rebased-From: 6763cb9bf540735ea32d2961a1b5348b5d261dcd Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 2 + src/qml/components/StorageLocations.qml | 27 +++++++++ src/qml/pages/onboarding/onboarding04.qml | 74 +++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 src/qml/components/StorageLocations.qml create mode 100644 src/qml/pages/onboarding/onboarding04.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 7491992279..614c629370 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -5,6 +5,7 @@ components/ConnectionOptions.qml components/ConnectionSettings.qml components/DeveloperOptions.qml + components/StorageLocations.qml components/StorageOptions.qml controls/ContinueButton.qml controls/Header.qml @@ -25,6 +26,7 @@ pages/onboarding/onboarding01c.qml pages/onboarding/onboarding02.qml pages/onboarding/onboarding03.qml + pages/onboarding/onboarding04.qml pages/stub.qml diff --git a/src/qml/components/StorageLocations.qml b/src/qml/components/StorageLocations.qml new file mode 100644 index 0000000000..6eeda83440 --- /dev/null +++ b/src/qml/components/StorageLocations.qml @@ -0,0 +1,27 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + ButtonGroup { + id: group + } + spacing: 15 + OptionButton { + ButtonGroup.group: group + text: qsTr("SD Card") + description: qsTr("The available space is large enough for full block storage. ") + recommended: true + checked: true + } + OptionButton { + ButtonGroup.group: group + text: qsTr("Hard drive") + description: qsTr("Available space only allows for partial block storage.") + } +} diff --git a/src/qml/pages/onboarding/onboarding04.qml b/src/qml/pages/onboarding/onboarding04.qml new file mode 100644 index 0000000000..4b5c8e6dc5 --- /dev/null +++ b/src/qml/pages/onboarding/onboarding04.qml @@ -0,0 +1,74 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Storage location") + description: qsTr("On which drive do you want to store the downloaded block data?") + descriptionMargin: 20 + } + StorageLocations { + Layout.topMargin: 30 + Layout.alignment: Qt.AlignCenter + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } + } +} \ No newline at end of file From 3d49c1fb5c3165d2ec9912876b35248468d31cd1 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 03:39:13 +0530 Subject: [PATCH 218/979] qml: Add onboarding05.qml page and its subpages - This includes the onboarding05.qml file and it subpages: - onboarding05a.qml : "Storage" - onboarding05b.qml : "Storage settings" - This commit also includes a components file to facilitate the onboarding05b.qml file Rebased-From: 72b85faf01643abf2b2525fb566ebe12cf49cfe0 Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 4 ++ src/qml/components/StorageOptions.qml | 2 - src/qml/components/StorageSettings.qml | 34 +++++++++ src/qml/pages/onboarding/onboarding05.qml | 27 +++++++ src/qml/pages/onboarding/onboarding05a.qml | 84 ++++++++++++++++++++++ src/qml/pages/onboarding/onboarding05b.qml | 59 +++++++++++++++ 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 src/qml/components/StorageSettings.qml create mode 100644 src/qml/pages/onboarding/onboarding05.qml create mode 100644 src/qml/pages/onboarding/onboarding05a.qml create mode 100644 src/qml/pages/onboarding/onboarding05b.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 614c629370..3f653294ae 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -7,6 +7,7 @@ components/DeveloperOptions.qml components/StorageLocations.qml components/StorageOptions.qml + components/StorageSettings.qml controls/ContinueButton.qml controls/Header.qml controls/Information.qml @@ -27,6 +28,9 @@ pages/onboarding/onboarding02.qml pages/onboarding/onboarding03.qml pages/onboarding/onboarding04.qml + pages/onboarding/onboarding05.qml + pages/onboarding/onboarding05a.qml + pages/onboarding/onboarding05b.qml pages/stub.qml diff --git a/src/qml/components/StorageOptions.qml b/src/qml/components/StorageOptions.qml index a335628ac7..d3f3a745ce 100644 --- a/src/qml/components/StorageOptions.qml +++ b/src/qml/components/StorageOptions.qml @@ -14,7 +14,6 @@ ColumnLayout { spacing: 15 OptionButton { ButtonGroup.group: group - Layout.fillWidth: true text: qsTr("Reduce storage") description: qsTr("Uses about 75GB.") recommended: true @@ -26,7 +25,6 @@ ColumnLayout { } OptionButton { ButtonGroup.group: group - Layout.fillWidth: true text: qsTr("Default") description: qsTr("Uses about 423GB.") detail: ProgressIndicator { diff --git a/src/qml/components/StorageSettings.qml b/src/qml/components/StorageSettings.qml new file mode 100644 index 0000000000..d7228179bf --- /dev/null +++ b/src/qml/components/StorageSettings.qml @@ -0,0 +1,34 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../controls" + +ColumnLayout { + spacing: 20 + Setting { + Layout.fillWidth: true + header: qsTr("Store Recent blocks only") + } + Information { + Layout.fillWidth: true + header: qsTr("Storage limit") + description: qsTr("75 GB") + isReadonly: false + } + Information { + Layout.fillWidth: true + header: qsTr("Data location") + description: qsTr("c://.../data") + isReadonly: false + } + Information { + Layout.fillWidth: true + header: qsTr("Block location") + description: qsTr("c://.../blocks") + isReadonly: false + } +} diff --git a/src/qml/pages/onboarding/onboarding05.qml b/src/qml/pages/onboarding/onboarding05.qml new file mode 100644 index 0000000000..85b918edc2 --- /dev/null +++ b/src/qml/pages/onboarding/onboarding05.qml @@ -0,0 +1,27 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + SwipeView { + id: storages + anchors.fill: parent + interactive: false + orientation: Qt.Vertical + Loader { + source:"onboarding05a.qml" + } + Loader { + source:"onboarding05b.qml" + } + } +} diff --git a/src/qml/pages/onboarding/onboarding05a.qml b/src/qml/pages/onboarding/onboarding05a.qml new file mode 100644 index 0000000000..9dbb564378 --- /dev/null +++ b/src/qml/pages/onboarding/onboarding05a.qml @@ -0,0 +1,84 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.11 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Storage") + description: qsTr("Data retrieved from the Bitcoin network is stored\non your device.\n\nYou have 500GB of storage available.") + } + StorageOptions { + Layout.topMargin: 30 + Layout.alignment: Qt.AlignCenter + } + TextButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 30 + text: "Detailed settings" + textSize: 18 + textColor: "#F7931A" + onClicked: { + storages.incrementCurrentIndex() + swipeView.inSubPage = true + } + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } + } +} diff --git a/src/qml/pages/onboarding/onboarding05b.qml b/src/qml/pages/onboarding/onboarding05b.qml new file mode 100644 index 0000000000..2ea54a394a --- /dev/null +++ b/src/qml/pages/onboarding/onboarding05b.qml @@ -0,0 +1,59 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.topMargin: 12 + Layout.rightMargin: -7 + sourceComponent: Item { + Layout.fillWidth: true + width: 73 + height: 46 + Text { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + text: "Done" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + MouseArea { + anchors.fill: parent + onClicked: { + storages.decrementCurrentIndex() + swipeView.inSubPage = false + } + } + } + } + } + ColumnLayout { + width: 450 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: "Storage settings" + } + StorageSettings { + Layout.topMargin: 30 + } + } +} From 6a083b9ab836f2ec35c860996fdab2708eff94a9 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 03:45:11 +0530 Subject: [PATCH 219/979] qml: Add onboarding06.qml pages and its subpages - This includes the main onboarding06.qml file along with its subpages: - onboarding06a.qml : "Connection" - onboarding06b.qml : "Connection settings" - This commit also updates the ConnectionSettings.qml component to better reflect the design file. Rebased-From: 233b721a2669b78aa3602102996510f16886b52e Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/bitcoin_qml.qrc | 3 + src/qml/components/ConnectionOptions.qml | 5 +- src/qml/components/ConnectionSettings.qml | 28 ++++++-- src/qml/pages/onboarding/onboarding06.qml | 27 +++++++ src/qml/pages/onboarding/onboarding06a.qml | 84 ++++++++++++++++++++++ src/qml/pages/onboarding/onboarding06b.qml | 59 +++++++++++++++ 6 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 src/qml/pages/onboarding/onboarding06.qml create mode 100644 src/qml/pages/onboarding/onboarding06a.qml create mode 100644 src/qml/pages/onboarding/onboarding06b.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 3f653294ae..400116f01a 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -31,6 +31,9 @@ pages/onboarding/onboarding05.qml pages/onboarding/onboarding05a.qml pages/onboarding/onboarding05b.qml + pages/onboarding/onboarding06.qml + pages/onboarding/onboarding06a.qml + pages/onboarding/onboarding06b.qml pages/stub.qml diff --git a/src/qml/components/ConnectionOptions.qml b/src/qml/components/ConnectionOptions.qml index 21a3d3079d..0f4cded500 100644 --- a/src/qml/components/ConnectionOptions.qml +++ b/src/qml/components/ConnectionOptions.qml @@ -14,21 +14,18 @@ ColumnLayout { spacing: 15 OptionButton { ButtonGroup.group: group - Layout.fillWidth: true text: qsTr("Fast always on") description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") recommended: true } OptionButton { ButtonGroup.group: group - Layout.fillWidth: true checked: true text: qsTr("Slow always on") - description: qsTr("Loads quickly at all times and uses as much cellular data as needed.") + description: qsTr("Loads at all times with reduced cellular data usage.") } OptionButton { ButtonGroup.group: group - Layout.fillWidth: true text: qsTr("Only when on Wi-Fi") description: qsTr("Loads quickly when on wi-fi and pauses when on cellular data.") detail: ProgressIndicator { diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml index 35f8e5d3ab..4bcf0d45c2 100644 --- a/src/qml/components/ConnectionSettings.qml +++ b/src/qml/components/ConnectionSettings.qml @@ -13,23 +13,39 @@ ColumnLayout { Layout.fillWidth: true header: qsTr("Use cellular data") } - Setting { + Information { Layout.fillWidth: true header: qsTr("Daily upload limit") + description: qsTr("250 MB") + isReadonly: false } - Setting { + Information { Layout.fillWidth: true header: qsTr("Connection limit") + description: qsTr("6") + isReadonly: false } Setting { Layout.fillWidth: true - header: qsTr("Listening enabled") - description: qsTr("Reduces data usage.") + header: qsTr("Enable listening") + description: qsTr("Increases data usage") } Setting { - last: true Layout.fillWidth: true header: qsTr("Blocks Only") - description: qsTr("Do not transfer unconfirmed transactions. Also disabled listening.") + description: qsTr("Reduces data usage.") + } + Information { + Layout.fillWidth: true + header: qsTr("Networks") + subtext: qsTr("Which networks to use for communication") + description: qsTr("6") + isReadonly: false + } + Information { + last: true + Layout.fillWidth: true + header: qsTr("Proxy settings") + description: qsTr(">") } } diff --git a/src/qml/pages/onboarding/onboarding06.qml b/src/qml/pages/onboarding/onboarding06.qml new file mode 100644 index 0000000000..e0fae57bdf --- /dev/null +++ b/src/qml/pages/onboarding/onboarding06.qml @@ -0,0 +1,27 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + SwipeView { + id: connections + anchors.fill: parent + interactive: false + orientation: Qt.Vertical + Loader { + source:"onboarding06a.qml" + } + Loader { + source:"onboarding06b.qml" + } + } +} diff --git a/src/qml/pages/onboarding/onboarding06a.qml b/src/qml/pages/onboarding/onboarding06a.qml new file mode 100644 index 0000000000..6f801566ce --- /dev/null +++ b/src/qml/pages/onboarding/onboarding06a.qml @@ -0,0 +1,84 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } + } + } + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Connection") + description: qsTr("Communicating with the Bitcoin network can use a lot of data.") + } + ConnectionOptions { + Layout.topMargin: 30 + Layout.alignment: Qt.AlignCenter + } + TextButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 30 + text: "Detailed Settings" + textSize: 18 + textColor: "#F7931A" + onClicked: { + connections.incrementCurrentIndex() + swipeView.inSubPage = true + } + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.finished = true + } + } +} diff --git a/src/qml/pages/onboarding/onboarding06b.qml b/src/qml/pages/onboarding/onboarding06b.qml new file mode 100644 index 0000000000..42ce1cd471 --- /dev/null +++ b/src/qml/pages/onboarding/onboarding06b.qml @@ -0,0 +1,59 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import "../../controls" +import "../../components" + +Page { + background: null + Layout.fillWidth: true + clip: true + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.topMargin: 12 + Layout.rightMargin: -7 + sourceComponent: Item { + Layout.fillWidth: true + width: 73 + height: 46 + Text { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + text: "Done" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + MouseArea { + anchors.fill: parent + onClicked: { + connections.decrementCurrentIndex() + swipeView.inSubPage = false + } + } + } + } + } + ColumnLayout { + width: 450 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Header { + Layout.fillWidth: true + bold: true + header: "Connection settings" + } + ConnectionSettings { + Layout.topMargin: 30 + } + } +} From 4eeab94341a3135564ac3265708eee79ba6b38f4 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 1 Jun 2022 03:51:10 +0530 Subject: [PATCH 220/979] qml: Update stub.qml to display onboarding views Rebased-From: 5118be447a705578eb90cf39a0971ddfc53f8d74 Github-Pull: bitcoin-core/gui-qml#124 --- src/qml/pages/stub.qml | 87 +++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/src/qml/pages/stub.qml b/src/qml/pages/stub.qml index 61baf5e2cf..30e244decc 100644 --- a/src/qml/pages/stub.qml +++ b/src/qml/pages/stub.qml @@ -10,48 +10,57 @@ import "../controls" ApplicationWindow { id: appWindow - title: "Bitcoin Core TnG" - minimumWidth: 750 - minimumHeight: 450 + title: "Bitcoin Core App" + minimumWidth: 640 + minimumHeight: 665 color: Theme.color.background visible: true - Component.onCompleted: nodeModel.startNodeInitializionThread(); + StackView { + id: main + initialItem: onboardingWizard + anchors.fill: parent + } - ColumnLayout { - anchors.centerIn: parent - spacing: 15 - width: 400 - Image { - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 64 - sourceSize.height: 64 - } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 0 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 25 - } - BlockCounter { - Layout.alignment: Qt.AlignCenter - blockHeight: nodeModel.blockTipHeight - } - ProgressIndicator { - id: indicator - Layout.fillWidth: true - progress: nodeModel.verificationProgress - } - ConnectionOptions { - Layout.preferredWidth: 400 - focus: true - } + Wizard { + id: onboardingWizard + anchors.fill: parent + views: [ + "onboarding/onboarding01.qml", + "onboarding/onboarding02.qml", + "onboarding/onboarding03.qml", + "onboarding/onboarding04.qml", + "onboarding/onboarding05.qml", + "onboarding/onboarding06.qml", + ] + onFinishedChanged: main.push(node) + } + Component { + id: node + Page { + anchors.fill: parent + background: null + ColumnLayout { + width: 600 + spacing: 0 + anchors.centerIn: parent + Component.onCompleted: nodeModel.startNodeInitializionThread(); + Image { + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 64 + sourceSize.height: 64 + } + BlockCounter { + Layout.alignment: Qt.AlignCenter + blockHeight: nodeModel.blockTipHeight + } + ProgressIndicator { + width: 200 + Layout.alignment: Qt.AlignCenter + progress: nodeModel.verificationProgress + } + } + } } } From b49d98d75edd0cf11e27e1066653e5987abdf9ae Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 1 Jun 2022 04:59:01 -0400 Subject: [PATCH 221/979] qml: handle undefined active state in header control Currently, when checking if the subtext or description labels should be active, the Header control doesn't handle the case where, for example, root.description is undefined. Here, we handle the case by initializing description and subtext as empty strings. Rebased-From: cc10229741d09ac2b93daef9d154bd9bb71046df Github-Pull: bitcoin-core/gui-qml#125 --- src/qml/controls/Header.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index c7adcf3097..913020a84e 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -13,10 +13,10 @@ Control { required property string header property int headerMargin property int headerSize: 28 - property string description + property string description: "" property int descriptionMargin: 10 property int descriptionSize: 18 - property string subtext + property string subtext: "" property int subtextMargin property int subtextSize: 15 property bool wrap: true From b4c93e1a9e1436bb7715763e049885c609eeab40 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 3 Aug 2022 05:16:03 -0400 Subject: [PATCH 222/979] qml: introduce ExternalLink control Control to handle storing and opening of external links. Can be just text or icon, or combination. Rebased-From: aadee41e0bfdf703b94c9d1e99af57b1c2f7dd32 Github-Pull: bitcoin-core/gui-qml#141 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/ExternalLink.qml | 49 +++++++++++++++++++++++++++++++ src/qml/controls/Header.qml | 4 +-- 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/qml/controls/ExternalLink.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 400116f01a..a67b528506 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -9,6 +9,7 @@ components/StorageOptions.qml components/StorageSettings.qml controls/ContinueButton.qml + controls/ExternalLink.qml controls/Header.qml controls/Information.qml controls/PageIndicator.qml diff --git a/src/qml/controls/ExternalLink.qml b/src/qml/controls/ExternalLink.qml new file mode 100644 index 0000000000..ac608d4551 --- /dev/null +++ b/src/qml/controls/ExternalLink.qml @@ -0,0 +1,49 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + required property string link + property string description: "" + property int descriptionSize: 18 + property url iconSource: "" + property int iconWidth: 30 + property int iconHeight: 30 + + contentItem: RowLayout { + spacing: 0 + width: parent.width + Loader { + Layout.fillWidth: true + active: root.description.length > 0 + visible: active + sourceComponent: Text { + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: root.descriptionSize + color: Theme.color.neutral7 + textFormat: Text.RichText + text: "" + "" + root.description + "" + onLinkActivated: Qt.openUrlExternally(link) + } + } + Loader { + Layout.fillWidth: true + active: root.iconSource.toString().length > 0 + visible: active + sourceComponent: Button { + icon.source: root.iconSource + icon.color: Theme.color.neutral9 + icon.height: root.iconHeight + icon.width: root.iconWidth + background: null + onClicked: Qt.openUrlExternally(link) + } + } + } +} diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 913020a84e..c7adcf3097 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -13,10 +13,10 @@ Control { required property string header property int headerMargin property int headerSize: 28 - property string description: "" + property string description property int descriptionMargin: 10 property int descriptionSize: 18 - property string subtext: "" + property string subtext property int subtextMargin property int subtextSize: 15 property bool wrap: true From 8e97420cc4ebdfd872f6ff5fc4b852b251701522 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 10 Aug 2022 23:30:01 -0400 Subject: [PATCH 223/979] qml: introduce arrow-up icon Rebased-From: 68d57200b440b18a3354125b8722bfeb89159d19 Github-Pull: bitcoin-core/gui-qml#151 --- src/qml/bitcoin_qml.qrc | 2 +- src/qml/controls/ExternalLink.qml | 49 ------------------------------ src/qml/imageprovider.cpp | 5 +++ src/qml/res/icons/arrow-up.png | Bin 0 -> 687 bytes src/qml/res/src/arrow-up.svg | 3 ++ 5 files changed, 9 insertions(+), 50 deletions(-) delete mode 100644 src/qml/controls/ExternalLink.qml create mode 100644 src/qml/res/icons/arrow-up.png create mode 100644 src/qml/res/src/arrow-up.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index a67b528506..5f02d3e679 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -9,7 +9,6 @@ components/StorageOptions.qml components/StorageSettings.qml controls/ContinueButton.qml - controls/ExternalLink.qml controls/Header.qml controls/Information.qml controls/PageIndicator.qml @@ -38,6 +37,7 @@ pages/stub.qml + res/icons/arrow-up.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png diff --git a/src/qml/controls/ExternalLink.qml b/src/qml/controls/ExternalLink.qml deleted file mode 100644 index ac608d4551..0000000000 --- a/src/qml/controls/ExternalLink.qml +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - required property string link - property string description: "" - property int descriptionSize: 18 - property url iconSource: "" - property int iconWidth: 30 - property int iconHeight: 30 - - contentItem: RowLayout { - spacing: 0 - width: parent.width - Loader { - Layout.fillWidth: true - active: root.description.length > 0 - visible: active - sourceComponent: Text { - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.descriptionSize - color: Theme.color.neutral7 - textFormat: Text.RichText - text: "" + "" + root.description + "" - onLinkActivated: Qt.openUrlExternally(link) - } - } - Loader { - Layout.fillWidth: true - active: root.iconSource.toString().length > 0 - visible: active - sourceComponent: Button { - icon.source: root.iconSource - icon.color: Theme.color.neutral9 - icon.height: root.iconHeight - icon.width: root.iconWidth - background: null - onClicked: Qt.openUrlExternally(link) - } - } - } -} diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 0bf54187ac..14697fa45b 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -22,6 +22,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return {}; } + if (id == "arrow-up") { + *size = requested_size; + return QIcon(":/icons/arrow-up").pixmap(requested_size); + } + if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); diff --git a/src/qml/res/icons/arrow-up.png b/src/qml/res/icons/arrow-up.png new file mode 100644 index 0000000000000000000000000000000000000000..6481eff063cb81eab7cc9c415f0b6159914ad3e2 GIT binary patch literal 687 zcmV;g0#N;lP)f7~6h+Z1W+?_UGc$7nru@w8Ak5A|%*@RAN9vl=^p<-2-Crc!eWzy0aY`wrlu}A5 zb%1v?)66^e6JZzVVP@%ixIko`p_`dC*UQCd=Pz9!7h|4p38I@H3Be`$nAze6xgPU; zOAyC=LvSO4`B4zq`LPmQHuEDOF!N(2xJ4uG4ovjZi2w)y8+w;q0M&#giUaDllkW$J%F1a^!XN`2vQN;4tqX~ zTYyjrt}@`5pBBIpbhrt^nV%j2PIw^jI{z$W3g9LPY`z63hR_JEIp${t;3l}UbLMy3 z`56MZ34)mqV-_F`0>^ys0C3y`K_>IhfPVltK^XHbKnY|(a2L;AWr!Jb9h@L-qZS|& zf~$C}oQA~t$H5PPgP@%ma}AW?tp}OSw*aN2?^q(iUA*-Y^RaT0N?=smj26IYVqD)o^YB1$P}QA?Nq=? z9#jxs0uVq{^$9=#>#kM+0uX=zVyYJb zth+h^2tWV=h^dBk^QR~wvfi!(_(^mfrhjGrI5&x~y}YKGPQG)JoTijgN-3q3QnTM% VQIXB|(C+{M002ovPDHLkV1h6H9>)Lx literal 0 HcmV?d00001 diff --git a/src/qml/res/src/arrow-up.svg b/src/qml/res/src/arrow-up.svg new file mode 100644 index 0000000000..5b1233b30e --- /dev/null +++ b/src/qml/res/src/arrow-up.svg @@ -0,0 +1,3 @@ + + + From 3213b3044a4d8a4fad409e9f1d180fac6865749f Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 3 Aug 2022 05:29:28 -0400 Subject: [PATCH 224/979] qml: introduce basic ValueInput control A basic user input text field. Rebased-From: 97288e253c24908424f029ecbd01a9d21628900b Github-Pull: bitcoin-core/gui-qml#142 --- src/qml/bitcoin_qml.qrc | 3 +- src/qml/controls/ExternalLink.qml | 49 ------------------------------ src/qml/controls/Header.qml | 4 +-- src/qml/controls/ValueInput.qml | 20 ++++++++++++ src/qml/imageprovider.cpp | 5 --- src/qml/res/icons/arrow-up.png | Bin 687 -> 0 bytes src/qml/res/src/arrow-up.svg | 3 -- 7 files changed, 23 insertions(+), 61 deletions(-) delete mode 100644 src/qml/controls/ExternalLink.qml create mode 100644 src/qml/controls/ValueInput.qml delete mode 100644 src/qml/res/icons/arrow-up.png delete mode 100644 src/qml/res/src/arrow-up.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index aee7ddd627..00e074e226 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -9,7 +9,6 @@ components/StorageOptions.qml components/StorageSettings.qml controls/ContinueButton.qml - controls/ExternalLink.qml controls/Header.qml controls/Information.qml controls/PageIndicator.qml @@ -20,6 +19,7 @@ controls/Setting.qml controls/TextButton.qml controls/Theme.qml + controls/ValueInput.qml controls/Wizard.qml pages/initerrormessage.qml pages/onboarding/onboarding01.qml @@ -38,7 +38,6 @@ pages/stub.qml - res/icons/arrow-up.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png diff --git a/src/qml/controls/ExternalLink.qml b/src/qml/controls/ExternalLink.qml deleted file mode 100644 index ac608d4551..0000000000 --- a/src/qml/controls/ExternalLink.qml +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - required property string link - property string description: "" - property int descriptionSize: 18 - property url iconSource: "" - property int iconWidth: 30 - property int iconHeight: 30 - - contentItem: RowLayout { - spacing: 0 - width: parent.width - Loader { - Layout.fillWidth: true - active: root.description.length > 0 - visible: active - sourceComponent: Text { - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.descriptionSize - color: Theme.color.neutral7 - textFormat: Text.RichText - text: "" + "" + root.description + "" - onLinkActivated: Qt.openUrlExternally(link) - } - } - Loader { - Layout.fillWidth: true - active: root.iconSource.toString().length > 0 - visible: active - sourceComponent: Button { - icon.source: root.iconSource - icon.color: Theme.color.neutral9 - icon.height: root.iconHeight - icon.width: root.iconWidth - background: null - onClicked: Qt.openUrlExternally(link) - } - } - } -} diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index 913020a84e..c7adcf3097 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -13,10 +13,10 @@ Control { required property string header property int headerMargin property int headerSize: 28 - property string description: "" + property string description property int descriptionMargin: 10 property int descriptionSize: 18 - property string subtext: "" + property string subtext property int subtextMargin property int subtextSize: 15 property bool wrap: true diff --git a/src/qml/controls/ValueInput.qml b/src/qml/controls/ValueInput.qml new file mode 100644 index 0000000000..5bbd644a87 --- /dev/null +++ b/src/qml/controls/ValueInput.qml @@ -0,0 +1,20 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +TextEdit { + id: root + property string description: "" + property int descriptionSize: 18 + + font.family: "Inter" + font.styleName: "Regular" + font.pixelSize: root.descriptionSize + color: Theme.color.neutral8 + text: description + horizontalAlignment: Text.AlignRight + wrapMode: Text.WordWrap +} diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 14697fa45b..0bf54187ac 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -22,11 +22,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return {}; } - if (id == "arrow-up") { - *size = requested_size; - return QIcon(":/icons/arrow-up").pixmap(requested_size); - } - if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); diff --git a/src/qml/res/icons/arrow-up.png b/src/qml/res/icons/arrow-up.png deleted file mode 100644 index 6481eff063cb81eab7cc9c415f0b6159914ad3e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 687 zcmV;g0#N;lP)f7~6h+Z1W+?_UGc$7nru@w8Ak5A|%*@RAN9vl=^p<-2-Crc!eWzy0aY`wrlu}A5 zb%1v?)66^e6JZzVVP@%ixIko`p_`dC*UQCd=Pz9!7h|4p38I@H3Be`$nAze6xgPU; zOAyC=LvSO4`B4zq`LPmQHuEDOF!N(2xJ4uG4ovjZi2w)y8+w;q0M&#giUaDllkW$J%F1a^!XN`2vQN;4tqX~ zTYyjrt}@`5pBBIpbhrt^nV%j2PIw^jI{z$W3g9LPY`z63hR_JEIp${t;3l}UbLMy3 z`56MZ34)mqV-_F`0>^ys0C3y`K_>IhfPVltK^XHbKnY|(a2L;AWr!Jb9h@L-qZS|& zf~$C}oQA~t$H5PPgP@%ma}AW?tp}OSw*aN2?^q(iUA*-Y^RaT0N?=smj26IYVqD)o^YB1$P}QA?Nq=? z9#jxs0uVq{^$9=#>#kM+0uX=zVyYJb zth+h^2tWV=h^dBk^QR~wvfi!(_(^mfrhjGrI5&x~y}YKGPQG)JoTijgN-3q3QnTM% VQIXB|(C+{M002ovPDHLkV1h6H9>)Lx diff --git a/src/qml/res/src/arrow-up.svg b/src/qml/res/src/arrow-up.svg deleted file mode 100644 index 5b1233b30e..0000000000 --- a/src/qml/res/src/arrow-up.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From 77f13d3a517f872a632bba8f559d50b2931e34fc Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Wed, 10 Aug 2022 23:50:15 -0400 Subject: [PATCH 225/979] qml: introduce arrow-down icon Rebased-From: e1c0b6ca1637f7d1ec9c01c975780c016d0ced37 Github-Pull: bitcoin-core/gui-qml#152 --- src/qml/bitcoin_qml.qrc | 2 +- src/qml/controls/ValueInput.qml | 20 -------------------- src/qml/imageprovider.cpp | 5 +++++ src/qml/res/icons/arrow-down.png | Bin 0 -> 712 bytes src/qml/res/src/arrow-down.svg | 3 +++ 5 files changed, 9 insertions(+), 21 deletions(-) delete mode 100644 src/qml/controls/ValueInput.qml create mode 100644 src/qml/res/icons/arrow-down.png create mode 100644 src/qml/res/src/arrow-down.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index bd87eda9ff..4c231ae1e1 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -20,7 +20,6 @@ controls/Setting.qml controls/TextButton.qml controls/Theme.qml - controls/ValueInput.qml controls/Wizard.qml pages/initerrormessage.qml pages/onboarding/onboarding01.qml @@ -39,6 +38,7 @@ pages/stub.qml + res/icons/arrow-down.png res/icons/arrow-up.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png diff --git a/src/qml/controls/ValueInput.qml b/src/qml/controls/ValueInput.qml deleted file mode 100644 index 5bbd644a87..0000000000 --- a/src/qml/controls/ValueInput.qml +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -TextEdit { - id: root - property string description: "" - property int descriptionSize: 18 - - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.descriptionSize - color: Theme.color.neutral8 - text: description - horizontalAlignment: Text.AlignRight - wrapMode: Text.WordWrap -} diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 14697fa45b..596153e439 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -22,6 +22,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return {}; } + if (id == "arrow-down") { + *size = requested_size; + return QIcon(":/icons/arrow-down").pixmap(requested_size); + } + if (id == "arrow-up") { *size = requested_size; return QIcon(":/icons/arrow-up").pixmap(requested_size); diff --git a/src/qml/res/icons/arrow-down.png b/src/qml/res/icons/arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..10b46c4a17d81ae0b9dc0ebb9721c2f932f1d007 GIT binary patch literal 712 zcmV;(0yq7MP)}WcNq70GWNhC@QsinISH;2Aq&7=#(k!6xLw^NJ?H6pZc+btR`9=9 z8#To#rIb=iDWx`Xg*Ljl&H*B9J@0Y9uZtZ-*CkxZ-6XnRBmjn)O=Pv<61PkM0uX=z zVyfK(SSkPk2q0zv0W2Z1Is_nqk`sUc77HMxfB*y_00GP;vibxdfRYn{0Ok-`{hN{WtHJs!qg*SsUzhAp2Y%iO4z)qgx_;L4GOQBuF{k;$DD+_?VyvO~$ z$4sNJRx*UM6W9U#`H8Eeuv&56c?1T4*-WN=e872kio$BanF;Iw{(S#hDXcj>&m`DS z{sznd+4J8pp8~6<8<)C|?4NRg{h9N-sioj*>BOb(3rCCqvvSV=m^r^0APj;*A0UkR zb^<%Vf#T-d369zU?DNAQ@BwC;<~IQZMUVyvZ9YIvCc#&Z8UO;BZzmY?0RotBAg}@) zEPQ?e1jlj#%oub2r();Z2|BU~3;+Slw-KZP^387q2$^8m2MBvUKy@C1G(cGM?F2r+ z^Z@1?2#)6lI26Eq3qcwnr1^G&u>rE@clq-}BWOzyjEo9!h|ihx8vy + + From 05767d988d007f81302344184683ef8af114bb8e Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 3 Aug 2022 05:59:16 -0400 Subject: [PATCH 226/979] qml: allow the settings component to load a dynamic action item. This extends the usability of the settings component so that it is able to load any action item. This means that this component can be used for all settings regardless of what action is meant to be on the right side. This prevents the need for endless mutations on the settings component to accomodate for different use-cases; the information component being one such mutation. Rebased-From: 40d48e7345b6af8ab6efe9f1869f25b3056290cc Github-Pull: bitcoin-core/gui-qml#143 --- src/qml/bitcoin_qml.qrc | 1 - src/qml/components/AboutOptions.qml | 77 ++++++++++------------ src/qml/components/ConnectionSettings.qml | 32 +++++---- src/qml/components/DeveloperOptions.qml | 28 ++++---- src/qml/components/StorageSettings.qml | 23 ++++--- src/qml/controls/Setting.qml | 11 ++-- src/qml/imageprovider.cpp | 5 -- src/qml/res/icons/arrow-down.png | Bin 712 -> 0 bytes src/qml/res/src/arrow-down.svg | 3 - 9 files changed, 93 insertions(+), 87 deletions(-) delete mode 100644 src/qml/res/icons/arrow-down.png delete mode 100644 src/qml/res/src/arrow-down.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index b091ca9ac1..bd87eda9ff 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -39,7 +39,6 @@ pages/stub.qml - res/icons/arrow-down.png res/icons/arrow-up.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png diff --git a/src/qml/components/AboutOptions.qml b/src/qml/components/AboutOptions.qml index 83f5922390..6ed4088943 100644 --- a/src/qml/components/AboutOptions.qml +++ b/src/qml/components/AboutOptions.qml @@ -9,56 +9,49 @@ import "../controls" ColumnLayout { spacing: 20 - Information { + Setting { Layout.fillWidth: true - header: qsTr("Website") - description: qsTr("bitcoincore.org >") - link: "https://bitcoincore.org" + header: qsTr("Website") + actionItem: ExternalLink { + description: qsTr("bitcoincore.org >") + link: "https://bitcoincore.org" + } } - Information { + Setting { Layout.fillWidth: true - header: qsTr("Source code") - description: qsTr("github.com/bitcoin/bitcoin >") - link: "https://github.com/bitcoin/bitcoin" + header: qsTr("Source code") + actionItem: ExternalLink { + description: qsTr("github.com/bitcoin/bitcoin >") + link: "https://github.com/bitcoin/bitcoin" + } } - Information { + Setting { Layout.fillWidth: true - header: qsTr("License") - description: qsTr("MIT >") - link: "https://opensource.org/licenses/MIT" + header: qsTr("License") + actionItem: ExternalLink { + description: qsTr("MIT >") + link: "https://opensource.org/licenses/MIT" + } } - Information { + Setting { Layout.fillWidth: true - header: qsTr("Version") - description: qsTr("v22.99.0-1e7564eca8a6 >") - link: "https://bitcoin.org/en/download" + header: qsTr("Version") + actionItem: ExternalLink { + description: qsTr("v22.99.0-1e7564eca8a6 >") + link: "https://bitcoin.org/en/download" + } } - RowLayout { - Header { - Layout.fillWidth: true - center: false - header: qsTr("Developer options") - headerSize: 18 - description: qsTr("Only use these if you have development experience") - descriptionSize: 15 - descriptionMargin: 10 - wrap: false - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - Layout.alignment: Qt.AlignRight - Layout.rightMargin: 5 - active: true - visible: active - sourceComponent: TextButton { - text: ">" - bold: false - rightalign: true - onClicked: { - introductions.incrementCurrentIndex() - swipeView.inSubPage = true - } + Setting { + Layout.fillWidth: true + header: qsTr("Developer options") + description: qsTr("Only use these if you have development experience") + actionItem: TextButton { + text: ">" + bold: false + rightalign: true + onClicked: { + introductions.incrementCurrentIndex() + swipeView.inSubPage = true } } } diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml index 4bcf0d45c2..38cc30af4c 100644 --- a/src/qml/components/ConnectionSettings.qml +++ b/src/qml/components/ConnectionSettings.qml @@ -12,40 +12,48 @@ ColumnLayout { Setting { Layout.fillWidth: true header: qsTr("Use cellular data") + actionItem: OptionSwitch{} } - Information { + Setting { Layout.fillWidth: true header: qsTr("Daily upload limit") - description: qsTr("250 MB") - isReadonly: false + actionItem: ValueInput { + description: qsTr("250 MB") + } } - Information { + Setting { Layout.fillWidth: true header: qsTr("Connection limit") - description: qsTr("6") - isReadonly: false + actionItem: ValueInput { + description: qsTr("6") + } } Setting { Layout.fillWidth: true header: qsTr("Enable listening") description: qsTr("Increases data usage") + actionItem: OptionSwitch {} } Setting { Layout.fillWidth: true header: qsTr("Blocks Only") description: qsTr("Reduces data usage.") + actionItem: OptionSwitch {} } - Information { + Setting { Layout.fillWidth: true header: qsTr("Networks") - subtext: qsTr("Which networks to use for communication") - description: qsTr("6") - isReadonly: false + description: qsTr("Which networks to use for communication") + actionItem: ValueInput { + description: qsTr("6") + } } - Information { + Setting { last: true Layout.fillWidth: true header: qsTr("Proxy settings") - description: qsTr(">") + actionItem: ValueInput { + description: qsTr(">") + } } } diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml index 1404168f0e..85a381d342 100644 --- a/src/qml/components/DeveloperOptions.qml +++ b/src/qml/components/DeveloperOptions.qml @@ -9,32 +9,38 @@ import "../controls" ColumnLayout { spacing: 20 - Information { + Setting { Layout.fillWidth: true header: qsTr("Developer documentation") - hasIcon: true - iconSource: "qrc:/icons/export" - link: "https://bitcoin.org/en/bitcoin-core/contribute/documentation" + actionItem: ExternalLink { + iconSource: "qrc:/icons/export" + link: "https://bitcoin.org/en/bitcoin-core/contribute/documentation" + } } Setting { Layout.fillWidth: true header: qsTr("Storage limit") + actionItem: OptionSwitch {} } - Information { + Setting { Layout.fillWidth: true header: qsTr("Network") - description: qsTr("Mainnet") - isReadonly: false + actionItem: ValueInput { + description: qsTr("Mainnet") + } } - Information { + Setting { Layout.fillWidth: true header: qsTr("Other option...") - description: qsTr("42") - isReadonly: false + actionItem: ValueInput { + description: qsTr("42") + } } Setting { Layout.fillWidth: true header: qsTr("Other option...") - description: qsTr("Description...") + actionItem: ValueInput { + description: qsTr("Description...") + } } } diff --git a/src/qml/components/StorageSettings.qml b/src/qml/components/StorageSettings.qml index d7228179bf..0ef026f1b4 100644 --- a/src/qml/components/StorageSettings.qml +++ b/src/qml/components/StorageSettings.qml @@ -12,23 +12,28 @@ ColumnLayout { Setting { Layout.fillWidth: true header: qsTr("Store Recent blocks only") + actionItem: OptionSwitch {} } - Information { + Setting { Layout.fillWidth: true header: qsTr("Storage limit") - description: qsTr("75 GB") - isReadonly: false + actionItem: ValueInput { + description: qsTr("75 GB") + } } - Information { + Setting { Layout.fillWidth: true header: qsTr("Data location") - description: qsTr("c://.../data") - isReadonly: false + actionItem: ValueInput { + description: qsTr("c://.../data") + } + } - Information { + Setting { Layout.fillWidth: true header: qsTr("Block location") - description: qsTr("c://.../blocks") - isReadonly: false + actionItem: ValueInput { + description: qsTr("c://.../blocks") + } } } diff --git a/src/qml/controls/Setting.qml b/src/qml/controls/Setting.qml index b11d6c3ca2..301302ca06 100644 --- a/src/qml/controls/Setting.qml +++ b/src/qml/controls/Setting.qml @@ -10,6 +10,7 @@ Control { id: root property bool last: parent && root === parent.children[parent.children.length - 1] required property string header + property alias actionItem: action_loader.sourceComponent property string description contentItem: ColumnLayout { spacing: 20 @@ -24,13 +25,15 @@ Control { descriptionSize: 15 descriptionMargin: 0 } - OptionSwitch { - Layout.alignment: Qt.AlignRight - Layout.rightMargin: -12 + Loader { + id: action_loader + active: true + visible: active + sourceComponent: root.actionItem } } Loader { - Layout.fillWidth:true + Layout.fillWidth: true Layout.columnSpan: 2 active: !last visible: active diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 596153e439..14697fa45b 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -22,11 +22,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return {}; } - if (id == "arrow-down") { - *size = requested_size; - return QIcon(":/icons/arrow-down").pixmap(requested_size); - } - if (id == "arrow-up") { *size = requested_size; return QIcon(":/icons/arrow-up").pixmap(requested_size); diff --git a/src/qml/res/icons/arrow-down.png b/src/qml/res/icons/arrow-down.png deleted file mode 100644 index 10b46c4a17d81ae0b9dc0ebb9721c2f932f1d007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 712 zcmV;(0yq7MP)}WcNq70GWNhC@QsinISH;2Aq&7=#(k!6xLw^NJ?H6pZc+btR`9=9 z8#To#rIb=iDWx`Xg*Ljl&H*B9J@0Y9uZtZ-*CkxZ-6XnRBmjn)O=Pv<61PkM0uX=z zVyfK(SSkPk2q0zv0W2Z1Is_nqk`sUc77HMxfB*y_00GP;vibxdfRYn{0Ok-`{hN{WtHJs!qg*SsUzhAp2Y%iO4z)qgx_;L4GOQBuF{k;$DD+_?VyvO~$ z$4sNJRx*UM6W9U#`H8Eeuv&56c?1T4*-WN=e872kio$BanF;Iw{(S#hDXcj>&m`DS z{sznd+4J8pp8~6<8<)C|?4NRg{h9N-sioj*>BOb(3rCCqvvSV=m^r^0APj;*A0UkR zb^<%Vf#T-d369zU?DNAQ@BwC;<~IQZMUVyvZ9YIvCc#&Z8UO;BZzmY?0RotBAg}@) zEPQ?e1jlj#%oub2r();Z2|BU~3;+Slw-KZP^387q2$^8m2MBvUKy@C1G(cGM?F2r+ z^Z@1?2#)6lI26Eq3qcwnr1^G&u>rE@clq-}BWOzyjEo9!h|ihx8vy - - From 34c28e9317eced619544a446c79fb4db620212d2 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 3 Aug 2022 05:59:39 -0400 Subject: [PATCH 227/979] qml: remove information qml This is no longer needed. Rebased-From: ee82e9c040a92a3324c4ad00502f974a258e737b Github-Pull: bitcoin-core/gui-qml#143 --- src/qml/bitcoin_qml.qrc | 1 - src/qml/controls/Information.qml | 88 -------------------------------- 2 files changed, 89 deletions(-) delete mode 100644 src/qml/controls/Information.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index bd87eda9ff..a6e86fb2cb 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -11,7 +11,6 @@ controls/ContinueButton.qml controls/ExternalLink.qml controls/Header.qml - controls/Information.qml controls/PageIndicator.qml controls/OptionButton.qml controls/OptionSwitch.qml diff --git a/src/qml/controls/Information.qml b/src/qml/controls/Information.qml deleted file mode 100644 index e5bf578fc4..0000000000 --- a/src/qml/controls/Information.qml +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property bool last: parent && root === parent.children[parent.children.length - 1] - required property string header - property string subtext - property int subtextMargin: 3 - property string description - property int descriptionMargin: 10 - property int descriptionSize: 18 - property bool isReadonly: true - property bool hasIcon: false - property string iconSource - property int iconWidth: 30 - property int iconHeight: 30 - property string link - contentItem: ColumnLayout { - spacing: 20 - width: parent.width - RowLayout { - Header { - Layout.fillWidth: true - center: false - header: root.header - headerSize: 18 - description: root.subtext - descriptionSize: 15 - descriptionMargin: root.subtextMargin - wrap: false - } - Loader { - Layout.fillWidth: true - Layout.preferredWidth: 0 - Layout.alignment: Qt.AlignRight | Qt.AlignHCenter - active: root.description.length > 0 - visible: active - sourceComponent: TextEdit { - font.family: "Inter" - font.styleName: "Regular" - font.pixelSize: root.descriptionSize - color: Theme.color.neutral8 - textFormat: Text.RichText - text: "" + "" + root.description + "" - readOnly: isReadonly - onLinkActivated: Qt.openUrlExternally(link) - horizontalAlignment: Text.AlignRight - wrapMode: Text.WordWrap - } - } - Loader { - Layout.preferredWidth: root.iconWidth - Layout.preferredHeight: root.iconHeight - Layout.alignment: Qt.AlignRight | Qt.AlignHCenter - active: root.hasIcon - visible: active - sourceComponent: Image { - horizontalAlignment: Image.AlignRight - source: root.iconSource - fillMode: Image.PreserveAspectFit - mipmap: true - MouseArea { - anchors.fill: parent - onClicked: { - Qt.openUrlExternally(link) - } - } - } - } - } - Loader { - Layout.fillWidth:true - Layout.columnSpan: 2 - active: !last - visible: active - sourceComponent: Rectangle { - height: 1 - color: Theme.color.neutral5 - } - } - } -} From 0b5d7e250808cc936bebda74058d3bd280c16393 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 3 Aug 2022 06:40:51 -0400 Subject: [PATCH 228/979] qml: use caret-right icon instead of greater than symbol Rebased-From: f9f692136f441ecee2686424c7fc38593bf44c82 Github-Pull: bitcoin-core/gui-qml#144 --- src/qml/components/AboutOptions.qml | 30 +++++++++++++++++------ src/qml/components/ConnectionSettings.qml | 8 ++++-- src/qml/components/DeveloperOptions.qml | 7 ------ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/qml/components/AboutOptions.qml b/src/qml/components/AboutOptions.qml index 6ed4088943..f6e2372f54 100644 --- a/src/qml/components/AboutOptions.qml +++ b/src/qml/components/AboutOptions.qml @@ -13,42 +13,56 @@ ColumnLayout { Layout.fillWidth: true header: qsTr("Website") actionItem: ExternalLink { - description: qsTr("bitcoincore.org >") + description: qsTr("bitcoincore.org") link: "https://bitcoincore.org" + iconSource: "image://images/caret-right" + iconWidth: 18 + iconHeight: 18 } } Setting { Layout.fillWidth: true header: qsTr("Source code") actionItem: ExternalLink { - description: qsTr("github.com/bitcoin/bitcoin >") + description: qsTr("github.com/bitcoin/bitcoin") link: "https://github.com/bitcoin/bitcoin" + iconSource: "image://images/caret-right" + iconWidth: 18 + iconHeight: 18 } } Setting { Layout.fillWidth: true header: qsTr("License") actionItem: ExternalLink { - description: qsTr("MIT >") + description: qsTr("MIT") link: "https://opensource.org/licenses/MIT" + iconSource: "image://images/caret-right" + iconWidth: 18 + iconHeight: 18 } } Setting { Layout.fillWidth: true header: qsTr("Version") actionItem: ExternalLink { - description: qsTr("v22.99.0-1e7564eca8a6 >") + description: qsTr("v22.99.0-1e7564eca8a6") link: "https://bitcoin.org/en/download" + iconSource: "image://images/caret-right" + iconWidth: 18 + iconHeight: 18 } } Setting { Layout.fillWidth: true header: qsTr("Developer options") description: qsTr("Only use these if you have development experience") - actionItem: TextButton { - text: ">" - bold: false - rightalign: true + actionItem: Button { + icon.source: "image://images/caret-right" + icon.color: Theme.color.neutral9 + icon.height: 18 + icon.width: 18 + background: null onClicked: { introductions.incrementCurrentIndex() swipeView.inSubPage = true diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml index 38cc30af4c..6553b32d8b 100644 --- a/src/qml/components/ConnectionSettings.qml +++ b/src/qml/components/ConnectionSettings.qml @@ -52,8 +52,12 @@ ColumnLayout { last: true Layout.fillWidth: true header: qsTr("Proxy settings") - actionItem: ValueInput { - description: qsTr(">") + actionItem: Button { + icon.source: "image://images/caret-right" + icon.color: Theme.color.neutral9 + icon.height: 18 + icon.width: 18 + background: null } } } diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml index a9f7d4ff02..85a381d342 100644 --- a/src/qml/components/DeveloperOptions.qml +++ b/src/qml/components/DeveloperOptions.qml @@ -29,13 +29,6 @@ ColumnLayout { description: qsTr("Mainnet") } } - Setting { - Layout.fillWidth: true - header: qsTr("Dark Mode") - actionItem: OptionSwitch { - onToggled: Theme.toggleDark() - } - } Setting { Layout.fillWidth: true header: qsTr("Other option...") From 7a3cbc5f324b9deedaa09c9ff9ba37aee3538104 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Wed, 10 Aug 2022 20:18:44 -0400 Subject: [PATCH 229/979] qml: temporary dark mode button Rebased-From: c2313810d272e7d17f417a7fb670d896b6b53aa2 Github-Pull: bitcoin-core/gui-qml#150 --- src/qml/components/DeveloperOptions.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml index 85a381d342..a9f7d4ff02 100644 --- a/src/qml/components/DeveloperOptions.qml +++ b/src/qml/components/DeveloperOptions.qml @@ -29,6 +29,13 @@ ColumnLayout { description: qsTr("Mainnet") } } + Setting { + Layout.fillWidth: true + header: qsTr("Dark Mode") + actionItem: OptionSwitch { + onToggled: Theme.toggleDark() + } + } Setting { Layout.fillWidth: true header: qsTr("Other option...") From 632b66d19a1bf695e56f212dd1c87f0178012db8 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 8 Aug 2022 00:32:04 -0400 Subject: [PATCH 230/979] qml: introduce OnboardingInfo control Represents the content of an onboarding page that displays an image, some body text, and the continue button. This type of onboarding page is thus categorized as in info page. Rebased-From: 653d677d36f5f283bffd812eec114852cda9dce8 Github-Pull: bitcoin-core/gui-qml#146 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/OnboardingInfo.qml | 59 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/qml/controls/OnboardingInfo.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 7fe7497ab8..1cb8e8b2cf 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -12,6 +12,7 @@ controls/ExternalLink.qml controls/Header.qml controls/PageIndicator.qml + controls/OnboardingInfo.qml controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml diff --git a/src/qml/controls/OnboardingInfo.qml b/src/qml/controls/OnboardingInfo.qml new file mode 100644 index 0000000000..5e490848f9 --- /dev/null +++ b/src/qml/controls/OnboardingInfo.qml @@ -0,0 +1,59 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + property alias banner: banner_loader.sourceComponent + required property string buttonText + property bool bold: false + property bool center: true + property int bannerMargin: 20 + required property string header + property int headerMargin: 30 + property int headerSize: 28 + property string description: "" + property int descriptionMargin: 20 + property int descriptionSize: 18 + property string subtext: "" + property int subtextMargin: 30 + property int subtextSize: 15 + + implicitWidth: 600 + + contentItem: ColumnLayout { + spacing: 0 + Loader { + id: banner_loader + active: true + visible: active + Layout.alignment: Qt.AlignCenter + Layout.topMargin: root.bannerMargin + sourceComponent: root.actionItem + } + Header { + Layout.fillWidth: true + bold: root.bold + center: root.center + header: root.header + headerMargin: root.headerMargin + headerSize: root.headerSize + description: root.description + descriptionMargin: root.descriptionMargin + descriptionSize: root.descriptionSize + subtext: root.subtext + subtextMargin: root.subtextMargin + subtextSize: root.subtextSize + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: root.buttonText + onClicked: swipeView.incrementCurrentIndex() + } + } +} From 3612d95aa41a43b4dea918e4b95ce1d4bcfdd6f7 Mon Sep 17 00:00:00 2001 From: jarolrod Date: Mon, 8 Aug 2022 00:33:35 -0400 Subject: [PATCH 231/979] qml: use OnboardingInfo control Use the OnboardingInfo control to simplify onboarding views that can be considered of the info type. Rebased-From: 661d4d2a4a6287bdfde829997f40edbe80faf785 Github-Pull: bitcoin-core/gui-qml#146 --- src/qml/pages/onboarding/onboarding01a.qml | 37 ++++++++------------- src/qml/pages/onboarding/onboarding02.qml | 38 +++++++--------------- src/qml/pages/onboarding/onboarding03.qml | 26 ++++----------- 3 files changed, 31 insertions(+), 70 deletions(-) diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index 784ef0260d..70ec4b0f2d 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -48,35 +48,24 @@ Page { } } } - ColumnLayout { - width: 600 - spacing: 0 - anchors.horizontalCenter: parent.horizontalCenter + OnboardingInfo { anchors.top: parent.top - Image { + anchors.horizontalCenter: parent.horizontalCenter + banner: Image { + Layout.fillWidth: true Layout.alignment: Qt.AlignCenter source: "image://images/app" sourceSize.width: 100 sourceSize.height: 100 } - Header { - Layout.fillWidth: true - implicitWidth: childrenRect.width - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - headerMargin: 30 - description: qsTr("Be part of the Bitcoin network.") - descriptionSize: 24 - descriptionMargin: 10 - subtext: qsTr("100% open-source & open-design") - subtextMargin: 30 - } - ContinueButton { - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 40 - text: "Start" - onClicked: swipeView.incrementCurrentIndex() - } + bannerMargin: 0 + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + description: qsTr("Be part of the Bitcoin network.") + descriptionMargin: 10 + descriptionSize: 24 + subtext: qsTr("100% open-source & open-design") + buttonText: "Start" } } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 1628a4ef1b..4419dc56e5 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -47,31 +47,17 @@ Page { } } } - ColumnLayout { - width: 600 - spacing: 0 - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - Image { - Layout.topMargin: 20 - Layout.alignment: Qt.AlignCenter - source: "image://images/app" - sourceSize.width: 200 - sourceSize.height: 200 - } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("Strengthen bitcoin") - headerMargin: 30 - description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") - descriptionMargin: 20 - } - ContinueButton { - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 40 - text: "Next" - onClicked: swipeView.incrementCurrentIndex() - } + OnboardingInfo { + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + banner: Image { + source: "image://images/app" + sourceSize.width: 200 + sourceSize.height: 200 + } + bold: true + header: qsTr("Strengthen bitcoin") + description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") + buttonText: "Next" } } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 5b127f9bd9..19cc6c9194 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -47,31 +47,17 @@ Page { } } } - ColumnLayout { - width: 600 - spacing: 0 + OnboardingInfo { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter - Image { - Layout.topMargin: 20 - Layout.alignment: Qt.AlignCenter + banner: Image { source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } - Header { - Layout.fillWidth: true - bold: true - header: qsTr("The block clock") - headerMargin: 30 - description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") - descriptionMargin: 20 - } - ContinueButton { - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 40 - text: "Next" - onClicked: swipeView.incrementCurrentIndex() - } + bold: true + header: qsTr("The block clock") + description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") + buttonText: "Next" } } From 7e0681b57d62c89772bfeacc382ba1e3b4f6cc7c Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sat, 13 Aug 2022 17:15:52 -0400 Subject: [PATCH 232/979] qml: introduce gear icon Rebased-From: 386591e0f9d09be7235f75a0e0d3fcea62d31e59 Github-Pull: bitcoin-core/gui-qml#154 --- src/qml/bitcoin_qml.qrc | 2 +- src/qml/controls/OnboardingInfo.qml | 59 --------------------- src/qml/imageprovider.cpp | 5 ++ src/qml/pages/onboarding/onboarding01a.qml | 37 ++++++++----- src/qml/pages/onboarding/onboarding02.qml | 38 ++++++++----- src/qml/pages/onboarding/onboarding03.qml | 26 ++++++--- src/qml/res/icons/gear.png | Bin 0 -> 1164 bytes src/qml/res/src/gear.svg | 3 ++ 8 files changed, 79 insertions(+), 91 deletions(-) delete mode 100644 src/qml/controls/OnboardingInfo.qml create mode 100644 src/qml/res/icons/gear.png create mode 100644 src/qml/res/src/gear.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 1cb8e8b2cf..0c990921f2 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -12,7 +12,6 @@ controls/ExternalLink.qml controls/Header.qml controls/PageIndicator.qml - controls/OnboardingInfo.qml controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml @@ -45,6 +44,7 @@ res/icons/caret-left.png res/icons/caret-right.png res/icons/export.png + res/icons/gear.png res/icons/info.png diff --git a/src/qml/controls/OnboardingInfo.qml b/src/qml/controls/OnboardingInfo.qml deleted file mode 100644 index 5e490848f9..0000000000 --- a/src/qml/controls/OnboardingInfo.qml +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property alias banner: banner_loader.sourceComponent - required property string buttonText - property bool bold: false - property bool center: true - property int bannerMargin: 20 - required property string header - property int headerMargin: 30 - property int headerSize: 28 - property string description: "" - property int descriptionMargin: 20 - property int descriptionSize: 18 - property string subtext: "" - property int subtextMargin: 30 - property int subtextSize: 15 - - implicitWidth: 600 - - contentItem: ColumnLayout { - spacing: 0 - Loader { - id: banner_loader - active: true - visible: active - Layout.alignment: Qt.AlignCenter - Layout.topMargin: root.bannerMargin - sourceComponent: root.actionItem - } - Header { - Layout.fillWidth: true - bold: root.bold - center: root.center - header: root.header - headerMargin: root.headerMargin - headerSize: root.headerSize - description: root.description - descriptionMargin: root.descriptionMargin - descriptionSize: root.descriptionSize - subtext: root.subtext - subtextMargin: root.subtextMargin - subtextSize: root.subtextSize - } - ContinueButton { - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 40 - text: root.buttonText - onClicked: swipeView.incrementCurrentIndex() - } - } -} diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 596153e439..bbb294c0b3 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -52,6 +52,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/export").pixmap(requested_size); } + if (id == "gear") { + *size = requested_size; + return QIcon(":/icons/gear").pixmap(requested_size); + } + if (id == "info") { *size = requested_size; return QIcon(":/icons/info").pixmap(requested_size); diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index 70ec4b0f2d..784ef0260d 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -48,24 +48,35 @@ Page { } } } - OnboardingInfo { - anchors.top: parent.top + ColumnLayout { + width: 600 + spacing: 0 anchors.horizontalCenter: parent.horizontalCenter - banner: Image { - Layout.fillWidth: true + anchors.top: parent.top + Image { Layout.alignment: Qt.AlignCenter source: "image://images/app" sourceSize.width: 100 sourceSize.height: 100 } - bannerMargin: 0 - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - description: qsTr("Be part of the Bitcoin network.") - descriptionMargin: 10 - descriptionSize: 24 - subtext: qsTr("100% open-source & open-design") - buttonText: "Start" + Header { + Layout.fillWidth: true + implicitWidth: childrenRect.width + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 10 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 30 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Start" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 4419dc56e5..1628a4ef1b 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -47,17 +47,31 @@ Page { } } } - OnboardingInfo { - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - banner: Image { - source: "image://images/app" - sourceSize.width: 200 - sourceSize.height: 200 - } - bold: true - header: qsTr("Strengthen bitcoin") - description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") - buttonText: "Next" + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 200 + sourceSize.height: 200 + } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Strengthen bitcoin") + headerMargin: 30 + description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 19cc6c9194..5b127f9bd9 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -47,17 +47,31 @@ Page { } } } - OnboardingInfo { + ColumnLayout { + width: 600 + spacing: 0 anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter - banner: Image { + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } - bold: true - header: qsTr("The block clock") - description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") - buttonText: "Next" + Header { + Layout.fillWidth: true + bold: true + header: qsTr("The block clock") + headerMargin: 30 + description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/res/icons/gear.png b/src/qml/res/icons/gear.png new file mode 100644 index 0000000000000000000000000000000000000000..da932781222d1fa281e84608b89d93adc1d49c8f GIT binary patch literal 1164 zcmV;71atd|P)&vfX5(){wqrVWAR6BJAU7a!ITcqKJWEK|%#??wjzj)Lr}u# zfC>4K|MPDJj6zWNWxyI<$-4o6a|Fe9PW~UQq&I)aqCZ2}iiBt_FVGH;KXhd|f|wox z#lo-XP4da+ToxgkP2p5B$mDkRA^{m#5fpP@(M(n%Nj8fKh&q!?K_)*U7W6F{7|{~3 zq^1~A#a6_Ewori~7a|sPKE`;whZyc7JPfL01!AyO{2#;mAqE?S1ztf6^#WGNXBJ|h zITT`vmh3?yZa2-b$lXZ9-G)^%nT$l(NHVZWKC6)kn~INBu0tZOFBZwuKINUwLv*7i z#Xnb*ZamB!M5_^4>(^s&MqWW>*<6V zbY?vgs>S#ibqHO#l9!kmdhT~3j4q*D&Ao;l4RrX3Cm|9l4P5Cn@ZBg=O_knE5n(oeKX`T!n#WPCdo90aufYH z5|7B_(wH-Ol#!u-&CZ0;HT2Ma&V!sn1F|uyLgSKHmk^U5_EO6dd@S*v#=?3zK8g5T zrLkf?TwO1VPoNt?x@&Iw8exrG?dL@1@(4YsNy*REqz8{`@ApTzTVw9#s7-R2g+$nR zva!muNW?viMS8FgiMW0ALMi^w3a;e;Sis|b#84mNVceC7!7jzH+H6M*wu5>Yl*1&% za8t>{nCB1+dKN<(BbL+%Bl;tj)DI)FEqQ5b1leZa8dNtSg~OzoA>K3{NeKoOGeUX& z=YF!t=2Ye+`Ql^-*C{W!jit!)rdMyCy^@NwsrCW zO86dO3+Lmdbkn;riFsVWR)p^;#zGl1r2@4>5oLSGMXiEnWKeB+Y(x}IC-z1liiQz; z>ixhi#NJhAPixHUjwm{km{acuw%`+c9<%rFPin$(yuh%49;K4BaU92S9LI4S$8j9T eaU92Se)bcRj*c14_J$V#0000 + + From a629961b3619b40558b475197d7db44d8028088e Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 14 Aug 2022 00:59:54 -0400 Subject: [PATCH 233/979] qml: temporarily set dark mode as default necessary to accommodate for static backups of elements that are supposed to be lottie animations. Can be reverted when we have developed proper lottie elements and have OS detection for light/dark mode. Rebased-From: 194c42dfe85afcd59a0e690807a874da2bf014f4 Github-Pull: bitcoin-core/gui-qml#155 --- src/qml/bitcoin_qml.qrc | 4 -- src/qml/components/DeveloperOptions.qml | 1 + src/qml/controls/NavButton.qml | 59 ---------------- src/qml/controls/OnboardingInfo.qml | 59 ---------------- src/qml/controls/OnboardingNav.qml | 26 ------- src/qml/controls/Theme.qml | 2 +- src/qml/imageprovider.cpp | 5 -- src/qml/pages/onboarding/onboarding01a.qml | 76 ++++++++++++++------ src/qml/pages/onboarding/onboarding01b.qml | 43 ++++++++++-- src/qml/pages/onboarding/onboarding01c.qml | 43 ++++++++++-- src/qml/pages/onboarding/onboarding02.qml | 77 ++++++++++++++++----- src/qml/pages/onboarding/onboarding03.qml | 65 ++++++++++++++--- src/qml/pages/onboarding/onboarding04.qml | 41 +++++++++-- src/qml/pages/onboarding/onboarding05a.qml | 39 +++++++++-- src/qml/pages/onboarding/onboarding05b.qml | 34 +++++++-- src/qml/pages/onboarding/onboarding06a.qml | 39 +++++++++-- src/qml/pages/onboarding/onboarding06b.qml | 34 +++++++-- src/qml/res/icons/gear.png | Bin 1164 -> 0 bytes src/qml/res/src/gear.svg | 3 - 19 files changed, 400 insertions(+), 250 deletions(-) delete mode 100644 src/qml/controls/NavButton.qml delete mode 100644 src/qml/controls/OnboardingInfo.qml delete mode 100644 src/qml/controls/OnboardingNav.qml delete mode 100644 src/qml/res/icons/gear.png delete mode 100644 src/qml/res/src/gear.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 3d43f25d04..7fe7497ab8 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -11,10 +11,7 @@ controls/ContinueButton.qml controls/ExternalLink.qml controls/Header.qml - controls/NavButton.qml controls/PageIndicator.qml - controls/OnboardingInfo.qml - controls/OnboardingNav.qml controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml @@ -47,7 +44,6 @@ res/icons/caret-left.png res/icons/caret-right.png res/icons/export.png - res/icons/gear.png res/icons/info.png diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml index a9f7d4ff02..aec2f36a76 100644 --- a/src/qml/components/DeveloperOptions.qml +++ b/src/qml/components/DeveloperOptions.qml @@ -33,6 +33,7 @@ ColumnLayout { Layout.fillWidth: true header: qsTr("Dark Mode") actionItem: OptionSwitch { + checked: Theme.dark onToggled: Theme.toggleDark() } } diff --git a/src/qml/controls/NavButton.qml b/src/qml/controls/NavButton.qml deleted file mode 100644 index 65b5a6e069..0000000000 --- a/src/qml/controls/NavButton.qml +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -AbstractButton { - id: root - property int iconHeight: 30 - property int iconWidth: 30 - property int textSize: 18 - property url iconSource: "" - - padding: 0 - background: null - contentItem: RowLayout { - anchors.fill: parent - spacing: 0 - Loader { - id: button_background - active: root.iconSource.toString().length > 0 - visible: active - sourceComponent: Button { - id: icon_button - padding: 0 - display: AbstractButton.IconOnly - height: root.iconHeight - width: root.iconWidth - icon.source: root.iconSource - icon.color: Theme.color.neutral9 - icon.height: root.iconHeight - icon.width: root.iconWidth - background: null - onClicked: root.clicked() - } - } - Loader { - active: root.text.length > 0 - visible: active - sourceComponent: AbstractButton { - id: container - padding: 0 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: root.textSize - background: null - contentItem: Text { - anchors.verticalCenter: parent.verticalCenter - font: container.font - color: Theme.color.neutral9 - text: root.text - } - onClicked: root.clicked() - } - } - } -} diff --git a/src/qml/controls/OnboardingInfo.qml b/src/qml/controls/OnboardingInfo.qml deleted file mode 100644 index 5e490848f9..0000000000 --- a/src/qml/controls/OnboardingInfo.qml +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property alias banner: banner_loader.sourceComponent - required property string buttonText - property bool bold: false - property bool center: true - property int bannerMargin: 20 - required property string header - property int headerMargin: 30 - property int headerSize: 28 - property string description: "" - property int descriptionMargin: 20 - property int descriptionSize: 18 - property string subtext: "" - property int subtextMargin: 30 - property int subtextSize: 15 - - implicitWidth: 600 - - contentItem: ColumnLayout { - spacing: 0 - Loader { - id: banner_loader - active: true - visible: active - Layout.alignment: Qt.AlignCenter - Layout.topMargin: root.bannerMargin - sourceComponent: root.actionItem - } - Header { - Layout.fillWidth: true - bold: root.bold - center: root.center - header: root.header - headerMargin: root.headerMargin - headerSize: root.headerSize - description: root.description - descriptionMargin: root.descriptionMargin - descriptionSize: root.descriptionSize - subtext: root.subtext - subtextMargin: root.subtextMargin - subtextSize: root.subtextSize - } - ContinueButton { - Layout.alignment: Qt.AlignCenter - Layout.topMargin: 40 - text: root.buttonText - onClicked: swipeView.incrementCurrentIndex() - } - } -} diff --git a/src/qml/controls/OnboardingNav.qml b/src/qml/controls/OnboardingNav.qml deleted file mode 100644 index 5f373fc84c..0000000000 --- a/src/qml/controls/OnboardingNav.qml +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -Control { - id: root - property alias navButton: button_loader.sourceComponent - property bool alignLeft: true - height: 46 - contentItem: RowLayout { - spacing: 0 - Layout.fillWidth: true - Loader { - id: button_loader - Layout.rightMargin: 10 - Layout.alignment: root.alignLeft ? Qt.AlignLeft : Qt.AlignRight - active: true - visible: active - sourceComponent: root.navButton - } - } -} diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index 0542f84120..bfd98a119a 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -2,7 +2,7 @@ pragma Singleton import QtQuick 2.15 QtObject { - property bool dark: false + property bool dark: true property QtObject color: QtObject { property color white: "#FFFFFF" property color background: dark ? "black" : "white" diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index bbb294c0b3..596153e439 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -52,11 +52,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/export").pixmap(requested_size); } - if (id == "gear") { - *size = requested_size; - return QIcon(":/icons/gear").pixmap(requested_size); - } - if (id == "info") { *size = requested_size; return QIcon(":/icons/info").pixmap(requested_size); diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index 24ac137e91..784ef0260d 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -14,35 +14,69 @@ Page { background: null clip: true Layout.fillWidth: true - header: OnboardingNav { - alignLeft: false - navButton: NavButton { - iconSource: "image://images/info" - iconHeight: 24 - onClicked: { - introductions.incrementCurrentIndex() - swipeView.inSubPage = true + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.margins: 11 + sourceComponent: Item { + width: 24 + height: 24 + Rectangle { + anchors.fill: parent + color: Theme.color.white + radius: width*0.5 + } + Image { + id: icon + source: "qrc:/icons/info" + width: parent.width + height: parent.height + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + mipmap: true + MouseArea { + anchors.fill: parent + onClicked: { + introductions.incrementCurrentIndex() + swipeView.inSubPage = true + } + } + } } } } - OnboardingInfo { - anchors.top: parent.top + ColumnLayout { + width: 600 + spacing: 0 anchors.horizontalCenter: parent.horizontalCenter - banner: Image { - Layout.fillWidth: true + anchors.top: parent.top + Image { Layout.alignment: Qt.AlignCenter source: "image://images/app" sourceSize.width: 100 sourceSize.height: 100 } - bannerMargin: 0 - bold: true - header: qsTr("Bitcoin Core App") - headerSize: 36 - description: qsTr("Be part of the Bitcoin network.") - descriptionMargin: 10 - descriptionSize: 24 - subtext: qsTr("100% open-source & open-design") - buttonText: "Start" + Header { + Layout.fillWidth: true + implicitWidth: childrenRect.width + bold: true + header: qsTr("Bitcoin Core App") + headerSize: 36 + headerMargin: 30 + description: qsTr("Be part of the Bitcoin network.") + descriptionSize: 24 + descriptionMargin: 10 + subtext: qsTr("100% open-source & open-design") + subtextMargin: 30 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Start" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/pages/onboarding/onboarding01b.qml b/src/qml/pages/onboarding/onboarding01b.qml index 65ac830ce2..16db8208ee 100644 --- a/src/qml/pages/onboarding/onboarding01b.qml +++ b/src/qml/pages/onboarding/onboarding01b.qml @@ -12,13 +12,42 @@ Page { background: null clip: true Layout.fillWidth: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: { - introductions.decrementCurrentIndex() - swipeView.inSubPage = false + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = false + } + } } } } diff --git a/src/qml/pages/onboarding/onboarding01c.qml b/src/qml/pages/onboarding/onboarding01c.qml index 0420c4e919..80ce7adcbb 100644 --- a/src/qml/pages/onboarding/onboarding01c.qml +++ b/src/qml/pages/onboarding/onboarding01c.qml @@ -12,13 +12,42 @@ Page { background: null clip: true Layout.fillWidth: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: { - introductions.decrementCurrentIndex() - swipeView.inSubPage = true + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = true + } + } } } } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 7e8855085b..1628a4ef1b 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -11,24 +11,67 @@ Page { background: null clip: true Layout.fillWidth: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: swipeView.currentIndex -= 1 + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } } } - OnboardingInfo { - anchors.top: parent.top - anchors.horizontalCenter: parent.horizontalCenter - banner: Image { - source: "image://images/app" - sourceSize.width: 200 - sourceSize.height: 200 - } - bold: true - header: qsTr("Strengthen bitcoin") - description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") - buttonText: "Next" + ColumnLayout { + width: 600 + spacing: 0 + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter + source: "image://images/app" + sourceSize.width: 200 + sourceSize.height: 200 + } + Header { + Layout.fillWidth: true + bold: true + header: qsTr("Strengthen bitcoin") + headerMargin: 30 + description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 39e4eaf1f1..5b127f9bd9 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -11,24 +11,67 @@ Page { background: null clip: true Layout.fillWidth: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: swipeView.currentIndex -= 1 + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } } } - OnboardingInfo { + ColumnLayout { + width: 600 + spacing: 0 anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter - banner: Image { + Image { + Layout.topMargin: 20 + Layout.alignment: Qt.AlignCenter source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } - bold: true - header: qsTr("The block clock") - description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") - buttonText: "Next" + Header { + Layout.fillWidth: true + bold: true + header: qsTr("The block clock") + headerMargin: 30 + description: qsTr("The Bitcoin network targets a new block every\n10 minutes. Sometimes it's faster and sometimes slower.\n\nThe block clock indicates each block on a dial\nthat represents the current day.") + descriptionMargin: 20 + } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() + } } } diff --git a/src/qml/pages/onboarding/onboarding04.qml b/src/qml/pages/onboarding/onboarding04.qml index 259bc0f2d0..4b5c8e6dc5 100644 --- a/src/qml/pages/onboarding/onboarding04.qml +++ b/src/qml/pages/onboarding/onboarding04.qml @@ -12,11 +12,40 @@ Page { background: null Layout.fillWidth: true clip: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: swipeView.currentIndex -= 1 + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } } } ColumnLayout { @@ -42,4 +71,4 @@ Page { onClicked: swipeView.incrementCurrentIndex() } } -} +} \ No newline at end of file diff --git a/src/qml/pages/onboarding/onboarding05a.qml b/src/qml/pages/onboarding/onboarding05a.qml index 7dfc79c222..9dbb564378 100644 --- a/src/qml/pages/onboarding/onboarding05a.qml +++ b/src/qml/pages/onboarding/onboarding05a.qml @@ -12,11 +12,40 @@ Page { background: null Layout.fillWidth: true clip: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: swipeView.currentIndex -= 1 + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } } } ColumnLayout { diff --git a/src/qml/pages/onboarding/onboarding05b.qml b/src/qml/pages/onboarding/onboarding05b.qml index b4840edec3..2ea54a394a 100644 --- a/src/qml/pages/onboarding/onboarding05b.qml +++ b/src/qml/pages/onboarding/onboarding05b.qml @@ -12,13 +12,33 @@ Page { background: null Layout.fillWidth: true clip: true - header: OnboardingNav { - alignLeft: false - navButton: NavButton { - text: "Done" - onClicked: { - storages.decrementCurrentIndex() - swipeView.inSubPage = false + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.topMargin: 12 + Layout.rightMargin: -7 + sourceComponent: Item { + Layout.fillWidth: true + width: 73 + height: 46 + Text { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + text: "Done" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + MouseArea { + anchors.fill: parent + onClicked: { + storages.decrementCurrentIndex() + swipeView.inSubPage = false + } + } } } } diff --git a/src/qml/pages/onboarding/onboarding06a.qml b/src/qml/pages/onboarding/onboarding06a.qml index 00059d4b5d..6f801566ce 100644 --- a/src/qml/pages/onboarding/onboarding06a.qml +++ b/src/qml/pages/onboarding/onboarding06a.qml @@ -12,11 +12,40 @@ Page { background: null Layout.fillWidth: true clip: true - header: OnboardingNav { - navButton: NavButton { - iconSource: "image://images/caret-left" - text: "Back" - onClicked: swipeView.currentIndex -= 1 + header: RowLayout { + height: 50 + Layout.leftMargin: 10 + Loader { + active: true + visible: active + sourceComponent: Item { + width: 73 + height: 46 + RowLayout { + anchors.fill: parent + spacing: 0 + Image { + source: "qrc:/icons/caret-left" + mipmap: true + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignVCenter + fillMode: Image.PreserveAspectFit + } + Text { + Layout.alignment: Qt.AlignVCenter + text: "Back" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + } + MouseArea { + anchors.fill: parent + onClicked: swipeView.currentIndex -= 1 + } + } } } ColumnLayout { diff --git a/src/qml/pages/onboarding/onboarding06b.qml b/src/qml/pages/onboarding/onboarding06b.qml index 8d82008a13..42ce1cd471 100644 --- a/src/qml/pages/onboarding/onboarding06b.qml +++ b/src/qml/pages/onboarding/onboarding06b.qml @@ -12,13 +12,33 @@ Page { background: null Layout.fillWidth: true clip: true - header: OnboardingNav { - alignLeft: false - navButton: NavButton { - text: "Done" - onClicked: { - connections.decrementCurrentIndex() - swipeView.inSubPage = false + header: RowLayout { + height: 50 + Loader { + active: true + visible: active + Layout.alignment: Qt.AlignRight + Layout.topMargin: 12 + Layout.rightMargin: -7 + sourceComponent: Item { + Layout.fillWidth: true + width: 73 + height: 46 + Text { + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + text: "Done" + color: Theme.color.neutral9 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + } + MouseArea { + anchors.fill: parent + onClicked: { + connections.decrementCurrentIndex() + swipeView.inSubPage = false + } + } } } } diff --git a/src/qml/res/icons/gear.png b/src/qml/res/icons/gear.png deleted file mode 100644 index da932781222d1fa281e84608b89d93adc1d49c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1164 zcmV;71atd|P)&vfX5(){wqrVWAR6BJAU7a!ITcqKJWEK|%#??wjzj)Lr}u# zfC>4K|MPDJj6zWNWxyI<$-4o6a|Fe9PW~UQq&I)aqCZ2}iiBt_FVGH;KXhd|f|wox z#lo-XP4da+ToxgkP2p5B$mDkRA^{m#5fpP@(M(n%Nj8fKh&q!?K_)*U7W6F{7|{~3 zq^1~A#a6_Ewori~7a|sPKE`;whZyc7JPfL01!AyO{2#;mAqE?S1ztf6^#WGNXBJ|h zITT`vmh3?yZa2-b$lXZ9-G)^%nT$l(NHVZWKC6)kn~INBu0tZOFBZwuKINUwLv*7i z#Xnb*ZamB!M5_^4>(^s&MqWW>*<6V zbY?vgs>S#ibqHO#l9!kmdhT~3j4q*D&Ao;l4RrX3Cm|9l4P5Cn@ZBg=O_knE5n(oeKX`T!n#WPCdo90aufYH z5|7B_(wH-Ol#!u-&CZ0;HT2Ma&V!sn1F|uyLgSKHmk^U5_EO6dd@S*v#=?3zK8g5T zrLkf?TwO1VPoNt?x@&Iw8exrG?dL@1@(4YsNy*REqz8{`@ApTzTVw9#s7-R2g+$nR zva!muNW?viMS8FgiMW0ALMi^w3a;e;Sis|b#84mNVceC7!7jzH+H6M*wu5>Yl*1&% za8t>{nCB1+dKN<(BbL+%Bl;tj)DI)FEqQ5b1leZa8dNtSg~OzoA>K3{NeKoOGeUX& z=YF!t=2Ye+`Ql^-*C{W!jit!)rdMyCy^@NwsrCW zO86dO3+Lmdbkn;riFsVWR)p^;#zGl1r2@4>5oLSGMXiEnWKeB+Y(x}IC-z1liiQz; z>ixhi#NJhAPixHUjwm{km{acuw%`+c9<%rFPin$(yuh%49;K4BaU92S9LI4S$8j9T eaU92Se)bcRj*c14_J$V#0000 - - From 38f4f137594298439548d450ced15ad862bf9303 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 8 Aug 2022 21:10:08 -0400 Subject: [PATCH 234/979] qml: introduce NavButton control Rebased-From: 061b3188d945ad270f8a27d618b291bc0096adb2 Github-Pull: bitcoin-core/gui-qml#147 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/NavButton.qml | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/qml/controls/NavButton.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 236506b904..a34554bd6b 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -11,6 +11,7 @@ controls/ContinueButton.qml controls/ExternalLink.qml controls/Header.qml + controls/NavButton.qml controls/PageIndicator.qml controls/OnboardingInfo.qml controls/OptionButton.qml diff --git a/src/qml/controls/NavButton.qml b/src/qml/controls/NavButton.qml new file mode 100644 index 0000000000..65b5a6e069 --- /dev/null +++ b/src/qml/controls/NavButton.qml @@ -0,0 +1,59 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +AbstractButton { + id: root + property int iconHeight: 30 + property int iconWidth: 30 + property int textSize: 18 + property url iconSource: "" + + padding: 0 + background: null + contentItem: RowLayout { + anchors.fill: parent + spacing: 0 + Loader { + id: button_background + active: root.iconSource.toString().length > 0 + visible: active + sourceComponent: Button { + id: icon_button + padding: 0 + display: AbstractButton.IconOnly + height: root.iconHeight + width: root.iconWidth + icon.source: root.iconSource + icon.color: Theme.color.neutral9 + icon.height: root.iconHeight + icon.width: root.iconWidth + background: null + onClicked: root.clicked() + } + } + Loader { + active: root.text.length > 0 + visible: active + sourceComponent: AbstractButton { + id: container + padding: 0 + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: root.textSize + background: null + contentItem: Text { + anchors.verticalCenter: parent.verticalCenter + font: container.font + color: Theme.color.neutral9 + text: root.text + } + onClicked: root.clicked() + } + } + } +} From 217d72b8eb53373a06d1c1c05024e1811c3f3502 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 8 Aug 2022 21:12:33 -0400 Subject: [PATCH 235/979] qml: introduce OnboardingNav control Rebased-From: 616864183eb94b99081d6e0c60a8d37323382945 Github-Pull: bitcoin-core/gui-qml#147 --- src/qml/bitcoin_qml.qrc | 1 + src/qml/controls/OnboardingNav.qml | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/qml/controls/OnboardingNav.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index a34554bd6b..3d43f25d04 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -14,6 +14,7 @@ controls/NavButton.qml controls/PageIndicator.qml controls/OnboardingInfo.qml + controls/OnboardingNav.qml controls/OptionButton.qml controls/OptionSwitch.qml controls/ProgressIndicator.qml diff --git a/src/qml/controls/OnboardingNav.qml b/src/qml/controls/OnboardingNav.qml new file mode 100644 index 0000000000..5f373fc84c --- /dev/null +++ b/src/qml/controls/OnboardingNav.qml @@ -0,0 +1,26 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +Control { + id: root + property alias navButton: button_loader.sourceComponent + property bool alignLeft: true + height: 46 + contentItem: RowLayout { + spacing: 0 + Layout.fillWidth: true + Loader { + id: button_loader + Layout.rightMargin: 10 + Layout.alignment: root.alignLeft ? Qt.AlignLeft : Qt.AlignRight + active: true + visible: active + sourceComponent: root.navButton + } + } +} From 977be31d68800f2cdeb005db0765b29e4c8c1bfb Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 8 Aug 2022 21:33:26 -0400 Subject: [PATCH 236/979] qml: onboarding views navbar cleanup Use the OnboardingNav and NavButton control to simplify the navbar of each onboarding view page and reduce the amount of duplicate code. Rebased-From: ff1b0f8b5893f001ac2cc6d64903c5b0aa792373 Github-Pull: bitcoin-core/gui-qml#147 --- src/qml/pages/onboarding/onboarding01a.qml | 39 ++++---------------- src/qml/pages/onboarding/onboarding01b.qml | 43 ++++------------------ src/qml/pages/onboarding/onboarding01c.qml | 43 ++++------------------ src/qml/pages/onboarding/onboarding02.qml | 39 +++----------------- src/qml/pages/onboarding/onboarding03.qml | 39 +++----------------- src/qml/pages/onboarding/onboarding04.qml | 41 +++------------------ src/qml/pages/onboarding/onboarding05a.qml | 39 +++----------------- src/qml/pages/onboarding/onboarding05b.qml | 34 ++++------------- src/qml/pages/onboarding/onboarding06a.qml | 39 +++----------------- src/qml/pages/onboarding/onboarding06b.qml | 34 ++++------------- 10 files changed, 62 insertions(+), 328 deletions(-) diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index 70ec4b0f2d..24ac137e91 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -14,37 +14,14 @@ Page { background: null clip: true Layout.fillWidth: true - header: RowLayout { - height: 50 - Loader { - active: true - visible: active - Layout.alignment: Qt.AlignRight - Layout.margins: 11 - sourceComponent: Item { - width: 24 - height: 24 - Rectangle { - anchors.fill: parent - color: Theme.color.white - radius: width*0.5 - } - Image { - id: icon - source: "qrc:/icons/info" - width: parent.width - height: parent.height - anchors.centerIn: parent - fillMode: Image.PreserveAspectFit - mipmap: true - MouseArea { - anchors.fill: parent - onClicked: { - introductions.incrementCurrentIndex() - swipeView.inSubPage = true - } - } - } + header: OnboardingNav { + alignLeft: false + navButton: NavButton { + iconSource: "image://images/info" + iconHeight: 24 + onClicked: { + introductions.incrementCurrentIndex() + swipeView.inSubPage = true } } } diff --git a/src/qml/pages/onboarding/onboarding01b.qml b/src/qml/pages/onboarding/onboarding01b.qml index 16db8208ee..65ac830ce2 100644 --- a/src/qml/pages/onboarding/onboarding01b.qml +++ b/src/qml/pages/onboarding/onboarding01b.qml @@ -12,42 +12,13 @@ Page { background: null clip: true Layout.fillWidth: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: { - introductions.decrementCurrentIndex() - swipeView.inSubPage = false - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = false } } } diff --git a/src/qml/pages/onboarding/onboarding01c.qml b/src/qml/pages/onboarding/onboarding01c.qml index 80ce7adcbb..0420c4e919 100644 --- a/src/qml/pages/onboarding/onboarding01c.qml +++ b/src/qml/pages/onboarding/onboarding01c.qml @@ -12,42 +12,13 @@ Page { background: null clip: true Layout.fillWidth: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: { - introductions.decrementCurrentIndex() - swipeView.inSubPage = true - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: { + introductions.decrementCurrentIndex() + swipeView.inSubPage = true } } } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 4419dc56e5..7e8855085b 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -11,40 +11,11 @@ Page { background: null clip: true Layout.fillWidth: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: swipeView.currentIndex -= 1 - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: swipeView.currentIndex -= 1 } } OnboardingInfo { diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 19cc6c9194..39e4eaf1f1 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -11,40 +11,11 @@ Page { background: null clip: true Layout.fillWidth: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: swipeView.currentIndex -= 1 - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: swipeView.currentIndex -= 1 } } OnboardingInfo { diff --git a/src/qml/pages/onboarding/onboarding04.qml b/src/qml/pages/onboarding/onboarding04.qml index 4b5c8e6dc5..259bc0f2d0 100644 --- a/src/qml/pages/onboarding/onboarding04.qml +++ b/src/qml/pages/onboarding/onboarding04.qml @@ -12,40 +12,11 @@ Page { background: null Layout.fillWidth: true clip: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: swipeView.currentIndex -= 1 - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: swipeView.currentIndex -= 1 } } ColumnLayout { @@ -71,4 +42,4 @@ Page { onClicked: swipeView.incrementCurrentIndex() } } -} \ No newline at end of file +} diff --git a/src/qml/pages/onboarding/onboarding05a.qml b/src/qml/pages/onboarding/onboarding05a.qml index 9dbb564378..7dfc79c222 100644 --- a/src/qml/pages/onboarding/onboarding05a.qml +++ b/src/qml/pages/onboarding/onboarding05a.qml @@ -12,40 +12,11 @@ Page { background: null Layout.fillWidth: true clip: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: swipeView.currentIndex -= 1 - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: swipeView.currentIndex -= 1 } } ColumnLayout { diff --git a/src/qml/pages/onboarding/onboarding05b.qml b/src/qml/pages/onboarding/onboarding05b.qml index 2ea54a394a..b4840edec3 100644 --- a/src/qml/pages/onboarding/onboarding05b.qml +++ b/src/qml/pages/onboarding/onboarding05b.qml @@ -12,33 +12,13 @@ Page { background: null Layout.fillWidth: true clip: true - header: RowLayout { - height: 50 - Loader { - active: true - visible: active - Layout.alignment: Qt.AlignRight - Layout.topMargin: 12 - Layout.rightMargin: -7 - sourceComponent: Item { - Layout.fillWidth: true - width: 73 - height: 46 - Text { - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - text: "Done" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - MouseArea { - anchors.fill: parent - onClicked: { - storages.decrementCurrentIndex() - swipeView.inSubPage = false - } - } + header: OnboardingNav { + alignLeft: false + navButton: NavButton { + text: "Done" + onClicked: { + storages.decrementCurrentIndex() + swipeView.inSubPage = false } } } diff --git a/src/qml/pages/onboarding/onboarding06a.qml b/src/qml/pages/onboarding/onboarding06a.qml index 6f801566ce..00059d4b5d 100644 --- a/src/qml/pages/onboarding/onboarding06a.qml +++ b/src/qml/pages/onboarding/onboarding06a.qml @@ -12,40 +12,11 @@ Page { background: null Layout.fillWidth: true clip: true - header: RowLayout { - height: 50 - Layout.leftMargin: 10 - Loader { - active: true - visible: active - sourceComponent: Item { - width: 73 - height: 46 - RowLayout { - anchors.fill: parent - spacing: 0 - Image { - source: "qrc:/icons/caret-left" - mipmap: true - Layout.preferredWidth: 30 - Layout.preferredHeight: 30 - Layout.alignment: Qt.AlignVCenter - fillMode: Image.PreserveAspectFit - } - Text { - Layout.alignment: Qt.AlignVCenter - text: "Back" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - } - MouseArea { - anchors.fill: parent - onClicked: swipeView.currentIndex -= 1 - } - } + header: OnboardingNav { + navButton: NavButton { + iconSource: "image://images/caret-left" + text: "Back" + onClicked: swipeView.currentIndex -= 1 } } ColumnLayout { diff --git a/src/qml/pages/onboarding/onboarding06b.qml b/src/qml/pages/onboarding/onboarding06b.qml index 42ce1cd471..8d82008a13 100644 --- a/src/qml/pages/onboarding/onboarding06b.qml +++ b/src/qml/pages/onboarding/onboarding06b.qml @@ -12,33 +12,13 @@ Page { background: null Layout.fillWidth: true clip: true - header: RowLayout { - height: 50 - Loader { - active: true - visible: active - Layout.alignment: Qt.AlignRight - Layout.topMargin: 12 - Layout.rightMargin: -7 - sourceComponent: Item { - Layout.fillWidth: true - width: 73 - height: 46 - Text { - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - text: "Done" - color: Theme.color.neutral9 - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - } - MouseArea { - anchors.fill: parent - onClicked: { - connections.decrementCurrentIndex() - swipeView.inSubPage = false - } - } + header: OnboardingNav { + alignLeft: false + navButton: NavButton { + text: "Done" + onClicked: { + connections.decrementCurrentIndex() + swipeView.inSubPage = false } } } From 405a90d74b587f8260ce2387f5a27990d0af6c78 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 15 Aug 2022 21:39:54 -0400 Subject: [PATCH 237/979] qml: introduce cross icon Rebased-From: 9848f2050d0a05dfca38d2485c0f49df84c21807 Github-Pull: bitcoin-core/gui-qml#162 --- src/qml/bitcoin_qml.qrc | 3 +- src/qml/controls/Theme.qml | 3 -- src/qml/imageprovider.cpp | 15 ++---- src/qml/pages/onboarding/onboarding03.qml | 2 +- src/qml/res/icons/blocktime-dark.png | Bin 19467 -> 0 bytes src/qml/res/icons/blocktime-light.png | Bin 18448 -> 0 bytes src/qml/res/icons/cross.png | Bin 0 -> 538 bytes src/qml/res/src/blocktime-dark.svg | 55 -------------------- src/qml/res/src/blocktime-light.svg | 60 ---------------------- src/qml/res/src/cross.svg | 4 ++ 10 files changed, 11 insertions(+), 131 deletions(-) delete mode 100644 src/qml/res/icons/blocktime-dark.png delete mode 100644 src/qml/res/icons/blocktime-light.png create mode 100644 src/qml/res/icons/cross.png delete mode 100644 src/qml/res/src/blocktime-dark.svg delete mode 100644 src/qml/res/src/blocktime-light.svg create mode 100644 src/qml/res/src/cross.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index f9e6a8bd8d..eda2193b8a 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -43,11 +43,10 @@ res/icons/arrow-down.png res/icons/arrow-up.png - res/icons/blocktime-dark.png - res/icons/blocktime-light.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png + res/icons/cross.png res/icons/export.png res/icons/gear.png res/icons/info.png diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index c4bc93c149..bfd98a119a 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -22,9 +22,6 @@ QtObject { property color neutral8: dark ? "#CCCCCC" : "#404040" property color neutral9: dark ? "#FFFFFF" : "#000000" } - property QtObject image: QtObject { - property url blocktime: dark ? "image://images/blocktime-dark" : "image://images/blocktime-light" - } function toggleDark() { dark = !dark } diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 6ee783054d..5a95b28d51 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,16 +32,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/arrow-up").pixmap(requested_size); } - if (id == "blocktime-dark") { - *size = requested_size; - return QIcon(":/icons/blocktime-dark").pixmap(requested_size); - } - - if (id == "blocktime-light") { - *size = requested_size; - return QIcon(":/icons/blocktime-light").pixmap(requested_size); - } - if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); @@ -57,6 +47,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/caret-right").pixmap(requested_size); } + if (id == "cross") { + *size = requested_size; + return QIcon(":/icons/cross").pixmap(requested_size); + } + if (id == "export") { *size = requested_size; return QIcon(":/icons/export").pixmap(requested_size); diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 8b81ea184b..39e4eaf1f1 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: Theme.image.blocktime + source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } diff --git a/src/qml/res/icons/blocktime-dark.png b/src/qml/res/icons/blocktime-dark.png deleted file mode 100644 index 2e34d95b4f79cd4a495bae0bb15c940bf231be6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19467 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 diff --git a/src/qml/res/icons/blocktime-light.png b/src/qml/res/icons/blocktime-light.png deleted file mode 100644 index ead9b4dd75071281ba3690134a3a422828a3a5fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18448 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 Hu0mjf3yUV) diff --git a/src/qml/res/icons/cross.png b/src/qml/res/icons/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..16d43af5332a8e3d76f030243107a9f9fd01811f GIT binary patch literal 538 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fh2BjaSW+oe0yhOu1KJW+e7=U z0wRqEJopL?ZZn*9ROHyk`u#xzi{N1=hTYj_N2P>X4oIE8`CIMBd69zBzI!R(_u4pU zE}atOg-q-@VYd6trn5Wep$O5wTL&q z@44ZmhTi7=#(%xrHlNNB(s^Q8)Th)$MK_wh?vHC|uNxyR1;!PiWt_5MIz zvmQ*DA9r63W}cn*gRhQFvt9oRUu2KDC!HYNe)C;Jv>MFV?VNl5X`1UbUbjzU>NZ<_ z$v+8XvBRs&EOGOJW|$zGex6u20euo*-;}Ps%c}ZJYpwl(_<8$I73{me++XOPv_-kmg|z|7S}|aRo2@7NlTD3?s@XQr@8ao3MQ_;lXlMZLOgGJ<(zip eXaL8`AGTldhu1O`Ot=D!a|TaWKbLh*2~7YhwhFue literal 0 HcmV?d00001 diff --git a/src/qml/res/src/blocktime-dark.svg b/src/qml/res/src/blocktime-dark.svg deleted file mode 100644 index dad783be78..0000000000 --- a/src/qml/res/src/blocktime-dark.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/blocktime-light.svg b/src/qml/res/src/blocktime-light.svg deleted file mode 100644 index 13de838d92..0000000000 --- a/src/qml/res/src/blocktime-light.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/cross.svg b/src/qml/res/src/cross.svg new file mode 100644 index 0000000000..1fcfaf2d03 --- /dev/null +++ b/src/qml/res/src/cross.svg @@ -0,0 +1,4 @@ + + + + From 828f2959939979097f29a83b1cad0e42f82268e2 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 15 Aug 2022 21:40:27 -0400 Subject: [PATCH 238/979] qml: introduce OutlineButton control Rebased-From: 4ecf1b5294bc49519b66ee0b82a1b798c4421bad Github-Pull: bitcoin-core/gui-qml#163 --- src/qml/bitcoin.cpp | 2 +- src/qml/bitcoin_qml.qrc | 8 +-- src/qml/controls/OutlineButton.qml | 29 +++++++++++ src/qml/controls/Theme.qml | 4 -- src/qml/imageprovider.cpp | 25 --------- src/qml/pages/onboarding/onboarding02.qml | 2 +- src/qml/pages/onboarding/onboarding03.qml | 2 +- src/qml/pages/{main.qml => stub.qml} | 0 src/qml/res/icons/blocktime-dark.png | Bin 19467 -> 0 bytes src/qml/res/icons/blocktime-light.png | Bin 18448 -> 0 bytes src/qml/res/icons/cross.png | Bin 538 -> 0 bytes src/qml/res/icons/network-dark.png | Bin 25693 -> 0 bytes src/qml/res/icons/network-light.png | Bin 26290 -> 0 bytes src/qml/res/src/blocktime-dark.svg | 55 -------------------- src/qml/res/src/blocktime-light.svg | 60 ---------------------- src/qml/res/src/cross.svg | 4 -- src/qml/res/src/network-dark.svg | 48 ----------------- src/qml/res/src/network-light.svg | 48 ----------------- 18 files changed, 34 insertions(+), 253 deletions(-) create mode 100644 src/qml/controls/OutlineButton.qml rename src/qml/pages/{main.qml => stub.qml} (100%) delete mode 100644 src/qml/res/icons/blocktime-dark.png delete mode 100644 src/qml/res/icons/blocktime-light.png delete mode 100644 src/qml/res/icons/cross.png delete mode 100644 src/qml/res/icons/network-dark.png delete mode 100644 src/qml/res/icons/network-light.png delete mode 100644 src/qml/res/src/blocktime-dark.svg delete mode 100644 src/qml/res/src/blocktime-light.svg delete mode 100644 src/qml/res/src/cross.svg delete mode 100644 src/qml/res/src/network-dark.svg delete mode 100644 src/qml/res/src/network-light.svg diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index e851755b98..c2475e13d8 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -184,7 +184,7 @@ int QmlGuiMain(int argc, char* argv[]) engine.rootContext()->setContextProperty("nodeModel", &node_model); - engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml"))); + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); if (engine.rootObjects().isEmpty()) { return EXIT_FAILURE; } diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 35a25ff892..2904834644 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -17,6 +17,7 @@ controls/OnboardingNav.qml controls/OptionButton.qml controls/OptionSwitch.qml + controls/OutlineButton.qml controls/ProgressIndicator.qml controls/qmldir controls/Setting.qml @@ -25,7 +26,6 @@ controls/ValueInput.qml controls/Wizard.qml pages/initerrormessage.qml - pages/main.qml pages/onboarding/onboarding01.qml pages/onboarding/onboarding01a.qml pages/onboarding/onboarding01b.qml @@ -39,21 +39,17 @@ pages/onboarding/onboarding06.qml pages/onboarding/onboarding06a.qml pages/onboarding/onboarding06b.qml + pages/stub.qml res/icons/arrow-down.png res/icons/arrow-up.png - res/icons/blocktime-dark.png - res/icons/blocktime-light.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png - res/icons/cross.png res/icons/export.png res/icons/gear.png res/icons/info.png - res/icons/network-dark.png - res/icons/network-light.png res/fonts/Inter-Regular.otf diff --git a/src/qml/controls/OutlineButton.qml b/src/qml/controls/OutlineButton.qml new file mode 100644 index 0000000000..10ce359d88 --- /dev/null +++ b/src/qml/controls/OutlineButton.qml @@ -0,0 +1,29 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Button { + font.family: "Inter" + font.styleName: "Semi Bold" + font.pixelSize: 18 + contentItem: Text { + text: parent.text + font: parent.font + color: Theme.color.neutral9 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + background: Rectangle { + implicitHeight: 46 + implicitWidth: 340 + color: Theme.color.background + radius: 5 + border { + width: 1 + color: Theme.color.neutral4 + } + } +} diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index e391bbdfb0..bfd98a119a 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -22,10 +22,6 @@ QtObject { property color neutral8: dark ? "#CCCCCC" : "#404040" property color neutral9: dark ? "#FFFFFF" : "#000000" } - property QtObject image: QtObject { - property url blocktime: dark ? "image://images/blocktime-dark" : "image://images/blocktime-light" - property url network: dark ? "image://images/network-dark" : "image://images/network-light" - } function toggleDark() { dark = !dark } diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index e690f84aa6..bbb294c0b3 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,16 +32,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/arrow-up").pixmap(requested_size); } - if (id == "blocktime-dark") { - *size = requested_size; - return QIcon(":/icons/blocktime-dark").pixmap(requested_size); - } - - if (id == "blocktime-light") { - *size = requested_size; - return QIcon(":/icons/blocktime-light").pixmap(requested_size); - } - if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); @@ -57,11 +47,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/caret-right").pixmap(requested_size); } - if (id == "cross") { - *size = requested_size; - return QIcon(":/icons/cross").pixmap(requested_size); - } - if (id == "export") { *size = requested_size; return QIcon(":/icons/export").pixmap(requested_size); @@ -77,15 +62,5 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/info").pixmap(requested_size); } - if (id == "network-dark") { - *size = requested_size; - return QIcon(":/icons/network-dark").pixmap(requested_size); - } - - if (id == "network-light") { - *size = requested_size; - return QIcon(":/icons/network-light").pixmap(requested_size); - } - return {}; } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 47a154d0b2..7e8855085b 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: Theme.image.network + source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 8b81ea184b..39e4eaf1f1 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: Theme.image.blocktime + source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } diff --git a/src/qml/pages/main.qml b/src/qml/pages/stub.qml similarity index 100% rename from src/qml/pages/main.qml rename to src/qml/pages/stub.qml diff --git a/src/qml/res/icons/blocktime-dark.png b/src/qml/res/icons/blocktime-dark.png deleted file mode 100644 index 2e34d95b4f79cd4a495bae0bb15c940bf231be6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19467 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 diff --git a/src/qml/res/icons/blocktime-light.png b/src/qml/res/icons/blocktime-light.png deleted file mode 100644 index ead9b4dd75071281ba3690134a3a422828a3a5fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18448 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 Hu0mjf3yUV) diff --git a/src/qml/res/icons/cross.png b/src/qml/res/icons/cross.png deleted file mode 100644 index 16d43af5332a8e3d76f030243107a9f9fd01811f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fh2BjaSW+oe0yhOu1KJW+e7=U z0wRqEJopL?ZZn*9ROHyk`u#xzi{N1=hTYj_N2P>X4oIE8`CIMBd69zBzI!R(_u4pU zE}atOg-q-@VYd6trn5Wep$O5wTL&q z@44ZmhTi7=#(%xrHlNNB(s^Q8)Th)$MK_wh?vHC|uNxyR1;!PiWt_5MIz zvmQ*DA9r63W}cn*gRhQFvt9oRUu2KDC!HYNe)C;Jv>MFV?VNl5X`1UbUbjzU>NZ<_ z$v+8XvBRs&EOGOJW|$zGex6u20euo*-;}Ps%c}ZJYpwl(_<8$I73{me++XOPv_-kmg|z|7S}|aRo2@7NlTD3?s@XQr@8ao3MQ_;lXlMZLOgGJ<(zip eXaL8`AGTldhu1O`Ot=D!a|TaWKbLh*2~7YhwhFue diff --git a/src/qml/res/icons/network-dark.png b/src/qml/res/icons/network-dark.png deleted file mode 100644 index 5f9279247ddedf76008a2de81f43f88d60dff9b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25693 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 oqiK3)G(*NFv!4q%F``ny|8&bWCj)tS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/blocktime-light.svg b/src/qml/res/src/blocktime-light.svg deleted file mode 100644 index 13de838d92..0000000000 --- a/src/qml/res/src/blocktime-light.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/cross.svg b/src/qml/res/src/cross.svg deleted file mode 100644 index 1fcfaf2d03..0000000000 --- a/src/qml/res/src/cross.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/qml/res/src/network-dark.svg b/src/qml/res/src/network-dark.svg deleted file mode 100644 index cee25614f8..0000000000 --- a/src/qml/res/src/network-dark.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/network-light.svg b/src/qml/res/src/network-light.svg deleted file mode 100644 index f798b6cb1d..0000000000 --- a/src/qml/res/src/network-light.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 4ca976d71b2834b9967aba7b033d866c45576743 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 14 Aug 2022 01:16:06 -0400 Subject: [PATCH 239/979] qml: introduce static backup for lottie blocktime element Rebased-From: 41bb56ce73308848035aecbcacbe57497f7afa37 Github-Pull: bitcoin-core/gui-qml#156 --- src/qml/bitcoin_qml.qrc | 2 + src/qml/imageprovider.cpp | 10 +++++ src/qml/res/icons/blocktime-dark.png | Bin 0 -> 19467 bytes src/qml/res/icons/blocktime-light.png | Bin 0 -> 18448 bytes src/qml/res/src/blocktime-dark.svg | 55 +++++++++++++++++++++++ src/qml/res/src/blocktime-light.svg | 60 ++++++++++++++++++++++++++ 6 files changed, 127 insertions(+) create mode 100644 src/qml/res/icons/blocktime-dark.png create mode 100644 src/qml/res/icons/blocktime-light.png create mode 100644 src/qml/res/src/blocktime-dark.svg create mode 100644 src/qml/res/src/blocktime-light.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 3d43f25d04..f9e6a8bd8d 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -43,6 +43,8 @@ res/icons/arrow-down.png res/icons/arrow-up.png + res/icons/blocktime-dark.png + res/icons/blocktime-light.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index bbb294c0b3..6ee783054d 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,6 +32,16 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/arrow-up").pixmap(requested_size); } + if (id == "blocktime-dark") { + *size = requested_size; + return QIcon(":/icons/blocktime-dark").pixmap(requested_size); + } + + if (id == "blocktime-light") { + *size = requested_size; + return QIcon(":/icons/blocktime-light").pixmap(requested_size); + } + if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); diff --git a/src/qml/res/icons/blocktime-dark.png b/src/qml/res/icons/blocktime-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2e34d95b4f79cd4a495bae0bb15c940bf231be6f GIT binary patch literal 19467 zcmX6^Wk6Kl)4sU6pe%yYy)^vj4vAH2NdZB+OF%)oQ>42)7o`O0?#`8^L`q2sLAv3+ z{@)M#VNahqbI+N1=9zFcRe8Ke6psJ^z*9iVXaE3K+`k_V6f6no5E=ylC5(d1b4?Gd z-8SqjBCYmY-;k`D02~;MCzu=)C5p|1M~EX$O;>GKpY~j|^9N1sSxxQS&uGz(&V+}6$mSUG z3-S*#8@Y&-P#8$OjE5$K#PKQge5^*!y)X~%PjK2f73X{9sOsd^utCjy(His6s86@C zXNPs+lL+(eZ&%ezJxA5s?>ii~4J-fMeqPBsMd>-pR(YW9S15jj+u8Pm`|2HqXGCH( z@t0t4-PZ`=3F1W=u&=w4Xn8dl4XbP;|HNdz#?CEsL$6K}&raQWQOnZw39d^|OWct6 zN$kXyTJJgKS|7-|&cDX907s+e3m4F!)X+91_<&^a%O;jlQgPj@QO*pFTj9FcRNu5a z&e>hm`>K8WLp;~tN?Ps+zfbT=sE^B~aEs)5vA9tJV@#DgNV)C@xXB zIc@!mXK_jyxOvF^QNf5o-RQ##>kq~L!-DM`-|Q9Lw94Jq(q~F^0Fb6zOKKJWoWe2_ ztM@x%3iALB&52B@oeA@=(FnB(|6<_y(p%RN-K61&einJe$w>wPj6=HxgeCYkU#Y!` z4w{3DQaJs2{u&6*3oWqTj=g3ZFQ7iTqG{6MxN&7>ipmE70<7uqsh7LDYs}59G2xcK zU~BEAb`_7rV=K*0a{D^wxcVekZ}K|KgU^-4=$>-q0KlgSJsD}sL2I(`&mq1qRSS6* zX|GLNL$Ke^ChdDnj!(wub^q{NU7z41XkPkqdj|9K?^ACaX%W1$ekANC&z9Yy&SsoG zQ~(2jny7KqEoxVU>e#t=X&5JdC!VgN4!?x7q^0rpG0N@5JLH#-8MuPDmzkM&22J&m zl}<_yMP?Uj(={SWZ2BG{di6iW`}nzyUD4@sl=HY#hk}WsQr};;T8A`3n^XEHY`0pi zZ2}x>7ZHk^tzO4Q#TcPTB$d>cq^M&}4by<#_ueo z+pXrcGW(3Q+|v|L05JLc#c)`>O%xLzLs4Y$ml#yakS|*I2OT=$xdqRIq`N8w$Cv(D zDTR_JVu$$Yym28AZsG?^N_rJu(?2n(?7wgE8C?U@$sPc~b8d8aQHOqV^+=Lk>20rF z<$LEfQ(EY5vq!US;ZDzQx0ca3@9s@X;onBj+|EE%aS@Y9|qbGD@&aq~6II~?-S29jt{ug?Pe3iYrTe$DO8h*RZ zCLM2{!xa0Vy}teOi&D^;>a}UNg_%1mv0X@Y5)@c_a}39;o8##ZyNQs*VTc}vRU0A- zHr{A($r}2a_9C|3q|~0C&&B79mo`|h7#qDB*{J-n|Koc+lN12NKg_XTZI_D)6W>;` z9Wi_K*B=_~O-rpZw_T~u>eQA(cb?jGU6WksZ1Skg;uC{WOUvHpEA)YsJ_j2XP!pXa z#C#S_^l9qjR8}8T!2Ueu`N?SRi|~+_=SmptnYq$MzaC=w>AfFUzd4-qdzkKUkb1k} zn?S&Q`QyCbc9To}Y8u?5d{0S@`!Exd=<0;#8}1y+>x;|b%Ems;Et0cQ_ZJ+7r%ZKb zKtQivJ%Q*`QIbqKl9HDiatgoFZP=_HOUoV%Om8^76r#%Zu0E<@ntEH7#kX8WJR3!7 zE6(n$bA1mWn4A7!O3@jVZujy(g}dN<9Ik=;MJ4syQOgl(e*UUq3&}l6JQwwqX6qhM zAgpXKlLp0st73k?L|7TZx*o|-JX@}BBkkKVfjMbE9NC)^q}p7o^ew`*rvJBgY zsyRom$KkGKK=5F~ndgQP@`9QByoLETg;b-lVe6axD&$aA^>8zSOvxbYH>e5exC~hE z%l>%FUr)6h7>~&xP#u@=$tXlJwGX>e-h8BpUAk)YP2XCHjR}7|iUhurtABgnC_Ci4 zg?bDN7%U?@z7oWsJJM}T)DN?r5a;(O3J$h%fcpC>$aW(uEe;LY_M})|393D5JzHv!fT(|KetEp zwqH-M+HN6rZx38f?*KrZLz+P#<~D8RgUqiuy9va94lm^R=uq)ff10gt)m6ScZWUK| zR4$hADr`HaE^?aYN$CbSw6h6J+e%>^T7fcs`t|R>Zs**>#*i5=tm<&pPkx?BqhB9x zmn;lt`wXnV(=7!8e(z^f=R4M#DgZ#JBB{msaLSiL#$Ki_wAa|Ue(H#wBk{YVW>Ul9 z1S(+l&2tKZKu4Iu;o%mbg$kvbo*LG@PVS06V<`3RuZi$B#7{v1NwnnD&+nONr`!YJ zdbHN@P9>%L&-s6KxLix-TAMypq6eJBpt1xB^Vkmq;Id`PuM{ps{qeao+s;oi{!m`= z08h`AzGVwA2gNOraD2oH*l+sMww-a1S4_&id84|w_&+fy#BCPsPJnFn=)=U@X#gBj2p?^(-?hub3}_mR}_0g#7x z+GJH&E5p*euZ6}ufdz>0#L}3ONbSC~9q)z$d0rc|@*{fa^d$>-WwmQVVqF*(t1KUU zG%MyY3@{;&u(l6$x4Sh;tcmY$&h~Eyi2VxjMhmsllwL#re*N*V^R30<&Zo;5&GHrn zm#ep91@{ruWfP_{ISe18;sKuJAZ%= zj{mK*^OFNl_S~bodiyZDy}j7+#JPFKYflmh&s{$4TQt$O_Y+*g zfEQt+%&FyG;Fo8x`R;*#rSE*ja$dH4!fam3xPE`sy#Q7PGoiv(2?)U0ebz#4!^qa4 zaC0c0VN+afr4`{l^CzoDfEg<j8@ zlrLley|R1K&`pdR42TmrU#Q{AYm2jO)A(CAUujG#@EER1n`zTOlJGMX8yJdg@L3|* z_R=94M)<6!E|QyxlSR`emMn^XYxFevLl}S>XfZbx22Hn~LLsz7WX>ZR{EY2(DS1v~ z$6R#HZ(iez(s&pu$HFY?dKiw`b{sR?3HxmL4<}Bfnl^&YUFA&F97_f z5$2_9WPPChgYpj{tDSF`1vCM_gFKBVw(2(?0S=&3N5J&5vHg(3rzp~jCr%R|L7KQR z5&r-HI@@hj)-O5b^w%$kwPVfUY?9}y%%kQoTfL9>0JWB#vzykKpc^@58Ar6=qLi~K zysPj_ltWtVj1ue~5Rh@$$8w>RF^Ffe$F4JmycWmzEUpMI2hIE90}d)B<^l;qN9Dgl zR30U)CJL<(Nce|km@?zT7{)p)C>8)r^9zqG&+#OA{!?;B4;%4#z8UrT;YLr3Q0)v* zjS17GUN{o%UXF=BIu+i%nx8T!#9!|CYPxLx>b(8zsR?sXX>%crTie+rveZXjFG}aPsoeQj|LXlxmox249yaes!=U^&t-%xk^bxZA{e&gx z%jK9k0~SKj-@1$8f#(dlfhyv;M6b~(^P3I_ogXg`CxY53@*vD6hiXk2>^IA zNZGkB)XGt8>}1?(LswR$cL=%3HvnKQ=VJKvvVHl0*HARaM&7sdiSDp$&=&r#{BHg7 zmEWRB>hG^B=`C@6_tWI%37Hg|YrX+QLzME(5ywY^J!7ZMl*jUZ~ZvU`h)=|!C zhtS{ojn-chDZ+|>?ywtsVMU6CdGTae`iVmjoud0ndP-ig$GG^pUYJZ&vPb_5tkw$h zGjhHs!?sdux)Ncsc)>eXe z6fahk_h+tcFZ_^8+)J2`o-m!zWdaxpk}4CUyWyd#7k4|l8XJn_Bu5^ooOqH_KH7I( zqy4-09TSbE1pR1*`UOp`Xy%I>me^ljJs4?Wggs)5S;?rH7}R*JGA*cdV@?}M!TJi5 z8mQ?j*PPJ)^8np2sBq6{wsw;d>Vz^~u6actOW)V|4e~@AiVzHP@Lc&TXhmOwSD7{2 zzms+zo#J_})Ty6%KYEGA9M3+Z!2-Vi*MAS??y+)UYK!d^@S~derkH#>C$HQk*I~Yn z^2P2>z3Hdto~NczJA)$oL%f_s>_%Ur#BpXrmCH1JbQ=sMAZR(_Ogz9CDs>o9dgP~R ze52RiFCt9E&anXvA%t-mQV$?XB^f50e5sgS@jNQmuZ3yoZlY_m<;OLl8aJYQC4%i2 z&!|c**>4L{xIF5u=Ic^<%=4(KyL@5;VJN2;TUhqA%h+wplh?wR*w<%x;(VuxUe$2m z-bY)vrS_<9&$D#y<}fjB2E4R^u%yS1J&Sd+0FGcY~pPFTX2)T{P01tv0JEp3E}MMXR@$jQB7`8Swt@e3!b;M$oa<|pzN{k z-jUozTVma{Nj1dW{Y-pt`@=@F?aWy>CQPr{gAey!kz&-z8Cf^tKPi??C%f|rix6+D ztyol7SHBsZ^)EuG?bhz+wW4L*)8d>mWhgFy@iTzr^(-gD7iP;uOm}Mv6Uxh; z`a7;^UWJc>{||8~i@f8jJ02`svix!4IQS_$MbpVOQW5_sBZlzLdw1Qbq(|9!Sg#D2 zaHFS24wJ`oyU0pE$MBiZ+~}4=9b{Mm?mOM~1ykV`YI6K~gWXPM={f-xmw~NZ#dCp(ZaLW4=8jUOsHE&+ST%qK1ax~DCyl?zB3!&(+9?r$9}8+&Y99+?^TfHj zopQ~3pc9)UDP8@jEPJPC+v}0DD9!#NEXY+~;IB0PdEMoV#O2Bfz(ZFEBeM zIxROLCwNyh+^4ZkCGn0iS@>{&Kh4Y^Gj1~;9sfht4j9nH$W_R;kGRL;hq%tge! z@mFtIP0`XkT>DHgp&M;G-TY*Tww~R%26Eo*Gx%lGFZwKliA~U{Y1}nOQLOu6OOFRu z#!JCnZ?}lq__Ij2?DDNj=1bZ+T{9{S_;~eJ`j@2_9T=TCi>7WH>Y`EoE#Gg3!`jX_u@K#|Mb zeb4Ojl{-dfj0rQu$ppT6H27V?R!K}H$p9V66M0=JHtVHd8^Lz(r>p9pi+H1wm~>G9 zhI$!1qGO3-QHWINd3*Wm*gkkfyNw($&1?L06YIlm;rX0?RI(aut;c@^qz&ROh`B`; zajt%!$G_2qBGQVBB17ypgK(aLu0NLB88bglX_gOKA4CMU#a5wS!-DaZ*Q6FGjBv&FwXq~#=s~Z~B4s4X zUm?lO!iA*M=9nYBl69Vx;eWez3uZm5;KxnB+?N>_+aI6@fQhneoY*XtK+|q4{;-A* zOZ(3D-15j23tR{y`~&w63yG@BRqmO`wV5?Vns2Q|Jj8?^eK060&EU1&9B{XkGu69p zvJdGU;;@iQS>gcw-~-YLB2GU7-S&weR{&334$AjQiW3?~WLf1}cpU$Hf3>k~mx+1+ z`0CBwtNwLayK2L2obn~ns$+}CVSI`;^r|2E&UmE?!Hf1Y7 zC#rJglTn0SzqbHkiFQ_^A&3Glb!MLCkOxbjh2H+&3fQ(V2T2ACa5K@my z)+=^?AeS6C^%aIvB0s+&#wYzT+qqi^fplJ4SBh@A=6GC3PJs%#>|R*7;j!THSJR(V zIv$(&i2E;DxF^gU_;xK z188^_80nQ({WrTaxcqtXwEp~qj-i1!q$W0pqZ!x@UjPjmZ1bv3tbpb}8Aq1y9HvWE zbgRy*KPiDGb_sc;Bp}E4u{L)grwtX(AqV_*UjM;GG(MkaO<(GL>dTQ4cF)N?P6TJ= zyNp+SPHL(|)fe$0eiRKyKY$p~yewLxzQ8_@c{VS1G~$`nE55=s`J@x6`qWpfpidqJ zx@?X?l`cyjy2(bl)?2%8{MbUlY41bew~Ad-^0sR;lW;4l&-}m&L1p1!p&fi(>5kx~ zYh{c%(EB-_>ZKlAK>-ClFP>wJCCUi&e&rm|bLH>go_KiPxw*Tv^MwZwb{+Dz?VX_r zGmD)ZrRJbxVGK4SsRErAcCqsH{43N6s)n$n`5v%DjoYIBybsd#M5k8jPem%Af5^coL1VX+ zoe+>w?*9HGr?r;|!3b|3sSR?ir4 z6-iH#c3W%pZ>DL4UZT^EU$cM3O2(n#AcmRPZoGaqn*V9b+h^b$a{DZwJ*Wv=GaisE z^5@o?U)YxSBD_Ek3vi6qt8$C*v-0XP8eg`1@@Kv5H3%Cc3|2Yyd3E%Dpv>0K-*6e@ zSv~~)8laDNBHtQ5)%5olSaxFZ|79Si-wa)0UFf^O9s9x)Hx5my)T<5#TL+*;9Z+w{ z%l!5Y$xmn7yAO#$>|FQb(si!qVtwFiGNhZ6tT8xjo@(%{jjZYPZnLFqZ?f#~`|n^J z#&wntK{pOCy4fGM-3qe4*773WlxbMeJ+@ffdq#33w?CA^7bkACz zIK=m$e37dXunKir(6jB#h zgED!MZ^4l5EQv6K5AcHpL(TEGU;SSE8kIkWS$GWF=Rp8K2$Q-+5$1fz5^s^$@K1pg z5-8B!RhLDJpMBTPBGjN5IWrpbe_zMi64ISS%T~rzaB8>JykwdE1vyeUJP^DD!A=>M zximwC%o@4uG2Mm{W#{^JF5@HZ5p@mI+IP-De}gLWVQcrp15y85M)-kAsbs#90P?UP z=bwsW%p|jWJn)ZW{{7J~hv)lv6q82Bw-z&j3yj-^Vzy@;JK8VDS~CnA%KvH^Io4FZ zJy>mz5Nr^h_EP27hp>nKlh6Z*g5BZG*}clL^UQDgt*@jC%`<2xWgZEB1y{(r*W^Dr zf_;!&NkRSwZpZ}X3oZfy0Dx#S>5NgZ>eGD+q(kuEd(m~@+EJ#c{FOUG`)XYYiC7Tb z9`liNoQgJvEia6ueU3Eh8B*eHYeTleYvq!kr3qdb zIc?k_gU4N^=kE8R03ze9UBQG5oyz-udAd&_HfV$f1x}kiy^U~emM!LKS>baeI}*D| zaF=B)I+T?ZnL0P&{32jy)TSMm!TNtRE8(xBRAie zwWFNn+}1^l_r?6!ko=uVy$cfrif3`y0zM<@QkfT5K1di!3Q{EycaO`uIq=AW@?6$P zmBM7@$06P**=f8Ug@`t`hQ#b9rG|ClnZu)0XXz-|S}y(3l@TS(LLl|%?C0$aN&2-X z2Q;ih-pZbujOYHkS8HAi_DW7m%tecmLd(m*?_-i{JAL|i5Z;tFAqJn|JP&+HK^z zTEi`IXTtfI559*JgfU8yPr|Z3hX($gsCy!iTe5MvVEa>?vQg4l<~^oah25kEB=gymu#>`58x?7LJCuRZ^TQ?dVauKgtu3?=TtY*iDuz{)QFv}^g4 zYIZZ9)nD5QH28)1OitU~D#6&Dm;W7p>3GZZT}KIYX1>&V;uRjYQO@tP$9K=A8KIc; zIY^k#pZ4!Rn{LNWn#70p*P9G-sf8$zgj=uMO6x&Uh*hAUDZjWsk}q7tN?$N|{5{f1 z`Ipv*xVj61B4U@v5tp_2VK^DIjgrfhS-vief{Ldkm&_M8S>W0+%#aJkcC<-mpmHs* z=mA3ox`5TMp2b;ohny!G=k3t+gxcNno|TF?ddbETgK?q{n-pNL2qyOap49!iUlQC2 zsftz82rtDH*T;#_5YHvA3UnMeLZ$hsDLzze`tcF1zzZieeUf)PSKo(EE@Gxee_m9q zUM`sB1=)oUVm0c%VX)Dl7oZ@VT^>AXN}H1@hsk7}aaN!WO|y=m6=?rLk7d<$rx{)X zl0YrRe~9iVeE-TEx^fS)!| zNI3{^+PSv89>di_uk}u%mPm}#7Mxt0hd?N6|ILmo5!E;Q|Fo{@j#3@t$dK$LoF?#^ zrmS#gwC>2s7FW!UoqBxB9g}Osp|2g?Q!{5|nam`L0s53Mm7jhH55=&B%Vo{JrHDyK zVXb(IWV>OoNt}3* zG|9S3LKpR0#ES5cQIt(EL9r{`8h$8)ac}hXAs7obS1&N?*MripSZ|7l2NLaC-5wHy zufTW#7R=&t>MM)p-C&=Kf@GDkOiB8>7=DN-y;qzyAN>|g<`!a!XT#kP13}?U+{WAF zaqjO8e(*^nv!^3dxknewa+_>AMi4l!fGVq7|aO7o_#z; zh$Yh0mT+I1s{cSy))20uk1Sz2LECJSsvX>3ey+QzUrpeVjafcrhX7;wqe6pzQwYS( z4b)&KL;OTNCQqW*LM2)AXg7>b=Kf?T3CV*8Pi+_bSdg%_O)~oeNL3)G(#+KhzN@dc z4|j5SmRIZF2){ktw2u>d@LRDe^@wpx3MFTs)qs4LC=mZ172d{PnWpfTd5kGJ%=@Z1 zTxc*9*(9`BctCOo+0Z3C6t_FLX-XT>9SSHa zwq%;S>h7%Zh%tnp)QJCbd}c*^`jgYpDWW1!gvFQgCPafL zRtS|{U1!7G)qPs{jMIxYdB<5XYTuidYqLT|m_V#vIQ57Wx8g#M%i1G&KOVi#VO|e3 z9_ryo)QS~b!a*OqX2QV+JQcz*JVSLAt=OLU+aSUxQhXtOesgNW#)+K>)eWbL2#r7W zN(@=PK7A)8FXCd`INyN|q(jb1*7b*#!Lnywr@R*}pFTKbF%MJzra)Rl%gd!}pJh-l z_R^$A)x3>Ku%WM;@Vw!`;EH)I-Ah#3bjne^2N4Y&xyXJn+Zs2LPSJG%>S__}JN4t- zt4xZQZ#6n3Doe(FQ_dZvud(rx$dK;P0zOItgF%jdMB`t=CpmWt73kMPJF||WpJkQ` z4TcvLOyHsh(`>)-hZi5Yv^T95pMB%vfmq)ht{KTj;<5UY5xM(<{iD1 zmlybAMo!-z!gLNy%Qv0+=Z}}jq1{|kbago93VYaGn{T&hB3i#0Gq8nj!As^`gGb1d z8P#=&4aVu^zKe9yG792OX0>l#Y9{FM>0{ki8L!|CT;XrCi55#i;{6Ez;0YXF3~tzY zgp7E`OwIhf5Q{fjb!ulRA{SZCgkl#>s@yJqgnGC7r^R`Kl1 zR?!{RP=Cww6Uz9Ity->y0J z&-vh`LnC2+&nZkzvVGZw`!zqzx`&6;FvP||$p>Tnb11E!KP5+g>caeyN+gNHz;fK5 z+QfD#4w(03`Cbp6l!T4%LW+x=X}^_xs0+PX+Trw5*rq@-L!Nx>jz4wwm5jpFz2)Ua z-c_ztbb+Z}K}ouo-y(4#TZl`^QAsv$WJ}Lm#5x#i zshx4%`6v}5Y)(}Y5@`*g=nE?!2RS>^nkIecgn_mTOmV}Ztq z)R#w@f&6!Wzs<{IAylSI=eU>bn4%{}XtbC&_8)V5_#xCB9p_gyC}Kn(U7JUY zV4EEvT%5!Hn>?PA?*M5GzX2o6!?b?wAT;mE$bGsoo6F4`J0AFKwwm z+KFc$12&Yx@}gUk7`BwrAGMDCS}$EZgT8xV2AHn~gu}z?#!$B;h9lx!)?AVQAsojR zP}blz)nC&!!QCXbJ*EMLAL3ZWSHKrly>wtp!q~y5Zc)EZiV`37o-8VQsRbWNvQ`{8 zVeV`AM=ra=W;cG_=c;lJAsehD{nddVfxfoK;GsSypv8xPQt!*QW`2URtY<+xn`_&w zAQWWI*-s&XjFyO7>DUSR>$UL(uR=DdtdLF_7x-G~%9w83kCoRLu{>?q{hy(@XyfZw z6*1N1AW-c8#?q;V@g6W;^Vif6QlckJFY@$W6CC)RHwoLdO%VsgH*KZ_ww3)Sdew%4 zZ|_CkE@Z1w1~=)wI3fwa%w$AaDBJ@Arxh}6%f^crk9uLo)B8do9btLBtl5pwVZq-F z#2Y}{Og<$6fDd*OksQbYxWF>B<{^(Mdqa5$y~cfOcQyR)26VJ^52Kec_P)^A3( zsu?Ax8l{;5@Jm~wP&M}y8IT=BV!gHDpTynrazB#KzzlAvs{vwN2+r&p%~^!OP@qf_A7XB8gde+5z#$Wm$bpAE#+(|o5--Gqmy#JUJ=%U<~p#!!9qxDN)E=qF( zr;;i~6=tY8v^IX1k;vbhP>!=>(tU##15}7ku4*{0-78F5R$U}19^(@V$HQzJ( zSJXDLcOR(2!)qY56gGc7y;!9B-G!3Bg7Ux2Lp`G zMwMJgQj@qma+hnTmYs1dwVfR2?#iJc zz0$dQA(jQfld2LeQd}r~5+0lDEV?Deh^qJQ-@P4g-y8k| z@Cf#y8i-+>Zv+Q(#PJo=9%C=a!WN-Vy#ckXzPoRR?M`Tql%cRZt{EhBWf3us@f<_o z5jKS+rL;otL9ha7My#gpR;?Gw|HaYbeV%||c_M!nDU{wwyZoT}^fg)7Z{9>sEAdDL zyI_*Uh~ADmoTE7^l?)j@`tha&fz%|H(W-PUXt(IT+<%Yr!%_7sdJ!LmLPhp1pI7b> zlYK34+;e+A`(7^0y!zg)gv3w3@~8QopA+rbKoyF+>rp5%$$_kmmM0 z!cbvESN88ahE=+Zi!2`giD@;SlF;{(6XUT|f-zRn5|9mEP(0BcV-O@zm$J@&i~JsDr4Q^ zBO~oNFYJX5=f1j~2O70JU*)}+xBeSi_N2CfmheLyKZ3j$QjolrT)ft0J;%FoK@Z=L zV!6`nn74`k`_Q$zUQ*3^i8#8zWNBiQI{mhN2>QK1*vxkbIYoFN5-O0+WkG@T zvm8;jc#{TAU?Dd#e+Tcw@()!ejjIrHjP@0<3V79XO*IqQ@vv9&>e|ATNbCkJobyI2 zJgVwpOVk5MlR&YiycFm!sP%}CM>EE&W!;HITUNc`)v<~{ly2+rcz35pT;MutO0i{8 zwIuawwNVQtAPuEQ6Xa5wg*(8vl=D^c>E}VCwm6arO3%3D93iry2vI0J>h&9X#Ba5S zpEV)k_K^(tGTfWjX!Vw)CJjP#7WM4-Oo};0cjinX*q_-U^~GACfxI3{yLv7-FzHQ} z6nk$~kKm}4YM6Oy2nCMdxOYbXa=OhFLZ&uKha zn1AOaPcWOr0(=LCr+FjJsQrIh@|-=D%py>x!r_21rxP6lbq!sBMgRt4GE;DEzhLOQyMB8?KeN)G9%T*b}ZB9pcL-E8bo#azs z)P%@BqRoIPdNwL~IwD~zl|pqGAEN^SKSjMVM~6#Z`f->=k?P5s+9p-0<26dH=1ZRW zIIiQUvRvA=k9AcV)>L(o664%vi->=I(==oX0Rs2da2h-d8XJQ+F6Oasb3SAElZbvh z4*t5Sro9vjC0SBMA#^2Uk!}i-brvbtn;*#WZ7A`f>$o4qz~&H4#{9^K!6rQB^>&&O z45(|NO)J*EQ*=c81nWk#o~N*@+d-eQJt`x#$?x9@`DhB4HD#u>$2n*Y$GVez#n&j? zgBTBc1xcrsg`_*Ef2qTR^*Ut@o@g1!W&ZX&p@Xf3>D8}@KU)%s7GU1;3WnpOvgJ08 z7kFS6PQ{GRA+vr>OYPxu<6VbuD8fYQts^K0=_6ql{1D!K-zCkn8&SdJ%!^||rs zRLp|KIYno4GlQeK)9k!)94Ta-h&3g`4hBJf8#v*Mch!6kDViQ$B9$Ff9P57PrnC{248~+=)r`U)fDXKK^jV5W@@Y8$nd+bh3+r9Uz^!h0}5%ip< zf((YAco7YJHgJeQ#jj(Y<^w#~+sblBWiH$o)wIsxSdetiJq2NmRdil}ADbLQ<|gmoe+=!)cZ zq8mtUUZwRy+Ne@b6`h}gIdXxbVVdJ$8V&FQrX2* z!ogv``!+83D3I@6*YKE?n($53vDM6rg-_V`Np?4LroR+Qm=r0&EMNuvD?bnwB$?kL zW$t2bQMKa-ltoy&?g-eSa^>=w&vr-pB66n5nQ42t;9r*Bzqk`->?nfxl}nsx@3X>+vJpqLezR0vmtpKWE(9Ep)jRNFEe#8<`)1$BvrS& z=0US9=1RgO-fNaiAAj)ZgEe_6oFg+^BCJ-lH8dtw1Dd|&x1+DYkwA8gZh41K@~mcu zZ%>{_B!rf}3}a_}4bBbtcUw*7yK`w$5!wnyvVaW#m#xeZ>xxsc;CNr_7UdQzq&Sbo zSW-f_Ju8wppD`G5`vvzRoOao4z|LvDRMg+5JQ5t{Pbi5t89(bZigQrYAI}P5VUuOg0;yjpFm}xtRx9fSpaj7WCaaMjqAv{tPm;(*yq^ z2x;#P&1C0C48oy&VD*#dnQQxYn?7sW!X?XKewnLjcrXXOQZXkOUL_z=+~Tll`H}H1 zQ=56^lPW3X|0C>aAxE5JMDi1_(*vjM^}Y29=#fdhj&Imk2Lrg8*BMZ z;O1)|Nx(i-PRXz-wiMPR?aCzM`1E78(|)Bau)UhWE2C65N*8oHOFCv(f7t6YZr#5~ zvp@pW+OWWmhW<=?uB}48dfImDT_+->`d?k=^0S7Iv+8Rpd%lgE73M=Btd0rqI%R^g z2tiHx$Ksn3ry^`{x_xnE@r7*e0p&L6k@!&}KpI_TFCymrzt=I=Ly@f~U(}#i;4T9K zVWt0kMSm&hKVKKgD^cCiZoRv z5J}p)d52bUxCSxrIFt~kU&RQH)M|-~{fd)aOOK;!`BMWJqTW62hF249jl=zfF-%m((+17ExUG^L9>ZvTuU%kD+#!coq*q0>Jxm zOlt+3!$@kyVa61u$eLfeQ%04ik=BVyNew*WOY@gx zc92Mtk}O6JDr!$ zYGOIHs&A-DM2&KbfjXCo_x~m6_#V^9-=YPd?dwp`SJyJsJb-bu;c;17GVPH*4#RR* zitGP%5{~m%tK#<`SEAQ8GJ1kDZ|8knk8N*E-w*M;p-&GdPk+!`xySijFLsuNB0ziG zZq-%wRwKc3=^M(=wY}rZ1Bm*ZCYpZzlV%ek*&wlpZvhw_n9`22$e7)`KAQUdCBr1Z z#+-3T?Y9SsC6My;8e02Fx)e-XyB<&h~v7|3;S@VLf6bl3xn7=Ds!UZ}-rf#*5a5NY9uoYv5upCvq zV*(rhQx)pX1D%v=CN2OtKV6zCbGu4m-*#K%mzrvveE)O*BghqOF&gOQt8-aeydGiV zBoAweo_zvU0Y#4o0RnJJ*o@!P*P#}V^p_9kDv$az-3@TMpg7yQ?gOh4C_{)cgQ%?6{w6Uf0>syGY%G`<)88ZEM zIWMy^W6GxPpRT3S9OO7lFMP*M|NayFHNWgTXUBMGRJGZ5} z-ZalO+C0m$NiyVIHA|s#8puPl`T_y2m)~iSur+`wq_F?u&J%BQN;iG4ES%0(s_e`@{`~w!e^gM>gl-^unQKuUMsEueVA9|8V zt$;A!tH17TZUZWItifl+Z3KOyTcQ7-9T+qtiJj=A!kV4b{}jC0L5oGsRmJzeZ&bx| zlek^WM;Y(54W+f*wJy&XG(X);f5@2zvu!A{@vbrj;`31{9N_yqrNyEAIlZ@m4j2Bq zyy+%wzo~=6yUngRo;C`Q!%U*WqnKSSKziZ8PL4a9>`UsYB{=$-LCwuZ^7G{b$cqX?)(FTC;5R$vHS3LFnKig zsQFXtJNlZ|z#}=$O=wE+g;lyhJckP$0+$3qV{(>}Eu553jFj@;s;aR@i9zgaJCAY%D=w)Z__=2w-uXd0tw0*>?DHVgK*h39$`0(%^dY1 zX%^ME`PNDZ@|Bx!7~D;l92GEu8=yXtB55)#P6g6La+pZ@fP$nZ$*3ed4anCndv;)` za|>kvqM4jM8^5xyE#J*W_`w2LS*SmSn$ph=l4EtINJ`ChSjHM(JcDdJPhYRO?f(BH z$=_XnDiXQr**{>iuz>E6BW``6;@ps8^H~r2cOm}e?`STjZRZMXK*FdlhJqp_JnF@~ z0npvElOr(z+VYoosreBdw*Qg_JNIX~m)yDX+wk_Q)L$n`mX#Si3&0| zCx;>d`ge3Z4f`Bu>|lMy=higxT9b=lI{&dlG~*urrj|jC!~X@d2~76m`~}SXL0tD0 z$PU9q#*lh406<9id*`;G1i#Jx{^MFpQ@+Y8{t*1#s;_=6-?we^I<;!u2nIlcM1u?@ z<%Xf5M`y7E0DSJb7bwm`r-2eAHBH|4E)Fg)g#AX4h(^+lG$u?V8GthJ1VGt!*VI@1 z5mO{?M81lZe@=@0D**f^ASr_)>wMTJ)pADw;5&-j`pb}Lw3OAAul%w*lWkuSz(_jl z^j?=~WU54K0ic#HnncT0JIoq~=v7`>zweR3ESUkwlnqmvq_zxzgPRW0wz07!v)T3Hbo$zT`>NV1j*14ub)>HHVXnup?;=ukb2&tU+hQi*tJ z-iTZoq&5tI#7)3W5Bv_OWvlKn(e$ZCbzDpx)y&VG}Vz56l%mO1BN$QEZK)`C$vSmG~(BVz~*06d; zp|dIe-+wZyeE16&U-T%03fPgb5;oRi=WLyNs@wHmEbQ<>N0ElhqZ+9{M&$Vz?ay+Ru11XK~r%E&rEVw&FYn0EqYUC}ODrW&(`YrRu4CQ1bYp ze_wi7m_u3=K@zY&qRZ*C17gr;+ z9K99zr>|+0d)p$ObZJs|At*lO9`m&Hm&ZFO|36?YV~Oe;a&4c+-;#`#KkHXYiy(e_ zsB5OQP$v=JT4+_Y_>VhdLU3EU6zA9bx%2CTh9{n1W%vF%X4f~=3J^5mWbY}tKL6o} zf!L0_B;ih=1YikW$4n5vV3-s{s|u$Q@vSGEPH2kwy8=?@fB86XQ$EIRCKq9Mj$LD( z!LBg_g`wu@@dqaKP+q&_8_T@Z4G{i_UyRb{)*ulcAU3ucbm|lgEn7N*xp^h6uYzEtk}CWx-W!~_!=u$P6d7a+fcpweyCkL41;9?21^LE zZEFhc+Ua4~{IK0WFxUJ)eu1+-w@}i7o9`9K&UYWf&T$T9XW1WSrdd5^rkG_glTG2B zW|;|bBL}E-I_()gLKX(=P?!`!D}V8OxWd9L)d>j=111A> zbY6p=-c3BgoW!8nhNqZN#pAIC4TeGU<~}ffd{qD_j26f-Kl-0S>CF7E7IZE2b_0dc z&i~4XNJ`2_2bW?-ORC5x`Wk1;kCrrI#`-kRmK*2SE@`i{V$Q}}7OjX@MfLcV-G;L> zZO^k)E#IhwgPO84Z0{)l4HJ*e4iGIs!YsMOb1Q5VYe@|b1VMajayH&lsP1P^Clbj3 z@xnp_wY6n1cdmoVH1)H)E!bhsdu6>$(`7w7!57=xf=!Ul^;Q0wa_R5^iXhO;%=B09 zZtF{DZnnhD|LY%Ng<8t^Xy?uHb-sNQ_Dm?NMGyq>1JzB6pp{UQTvzgXdJg{H;UU&1E6Njb&6s* z)-1kDfYhtEQzbwK+F#T(K+r5mOl&A@^eaLZi4q`D{YR-hZe#AY;H4g0v4+8O5wJg5AP8`FE`){cwiqe{vEUtrp>hpFCG8tL!dkBqAOmc#i4Y)= ze&a%0p#~D#Ym&wRGR^9F`UAz+tcO-dwb62DQB=9(j35Yt04=S*F;uEUixwUjEaUOC zA_YUk^H8-aFIs@KZoNV!K>FKU7bQS$pKl|y-0oW7`=x=A-L1vWuseh8y|L^9k5MUm z<{OIe`h0>Q2mBvYrlsuZS2drLJg zq7Sq`pX;{1rG9I&JE>4WGch1uVQcOsW|sXNhCy<;c_%?zkfV-3`;y8`<3u?GM{)Fj7h>DNy-Wrn$I zmGv=auo%vNLQdAl^0BP1#UrMl^%aE!ZI80U-B+fa-d#6mrlLGr8ZC|%PS`rS9Jee` h2e$S2rA`tA@js`YUl=J9D)RsU002ovPDHLkV1m0L*D?SA literal 0 HcmV?d00001 diff --git a/src/qml/res/icons/blocktime-light.png b/src/qml/res/icons/blocktime-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ead9b4dd75071281ba3690134a3a422828a3a5fc GIT binary patch literal 18448 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 Hu0mjf3yUV) literal 0 HcmV?d00001 diff --git a/src/qml/res/src/blocktime-dark.svg b/src/qml/res/src/blocktime-dark.svg new file mode 100644 index 0000000000..dad783be78 --- /dev/null +++ b/src/qml/res/src/blocktime-dark.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qml/res/src/blocktime-light.svg b/src/qml/res/src/blocktime-light.svg new file mode 100644 index 0000000000..13de838d92 --- /dev/null +++ b/src/qml/res/src/blocktime-light.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 13060ee66d0e6012b326b2cbc8fd40b1cc3a0a8d Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 14 Aug 2022 01:21:31 -0400 Subject: [PATCH 240/979] qml: use static backup for lottie blocktime element Rebased-From: 1bbe1e506e62ec1d0f2ab173741719eb4ada2900 Github-Pull: bitcoin-core/gui-qml#156 --- src/qml/controls/Theme.qml | 3 +++ src/qml/pages/onboarding/onboarding03.qml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index bfd98a119a..c4bc93c149 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -22,6 +22,9 @@ QtObject { property color neutral8: dark ? "#CCCCCC" : "#404040" property color neutral9: dark ? "#FFFFFF" : "#000000" } + property QtObject image: QtObject { + property url blocktime: dark ? "image://images/blocktime-dark" : "image://images/blocktime-light" + } function toggleDark() { dark = !dark } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 39e4eaf1f1..8b81ea184b 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: "image://images/app" + source: Theme.image.blocktime sourceSize.width: 200 sourceSize.height: 200 } From bea5357917bddbf6f0c36cef1718974be5241a8b Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 14 Aug 2022 01:25:04 -0400 Subject: [PATCH 241/979] qml: introduce static backup for lottie network element Rebased-From: df95b88bb5d092c42d012b57fc395f31ba422210 Github-Pull: bitcoin-core/gui-qml#157 --- src/qml/bitcoin_qml.qrc | 2 ++ src/qml/imageprovider.cpp | 10 ++++++ src/qml/res/icons/network-dark.png | Bin 0 -> 25693 bytes src/qml/res/icons/network-light.png | Bin 0 -> 26290 bytes src/qml/res/src/network-dark.svg | 48 ++++++++++++++++++++++++++++ src/qml/res/src/network-light.svg | 48 ++++++++++++++++++++++++++++ 6 files changed, 108 insertions(+) create mode 100644 src/qml/res/icons/network-dark.png create mode 100644 src/qml/res/icons/network-light.png create mode 100644 src/qml/res/src/network-dark.svg create mode 100644 src/qml/res/src/network-light.svg diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 405cb7f93c..f063c09130 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -52,6 +52,8 @@ res/icons/export.png res/icons/gear.png res/icons/info.png + res/icons/network-dark.png + res/icons/network-light.png res/fonts/Inter-Regular.otf diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 1a114c087b..e690f84aa6 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -77,5 +77,15 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/info").pixmap(requested_size); } + if (id == "network-dark") { + *size = requested_size; + return QIcon(":/icons/network-dark").pixmap(requested_size); + } + + if (id == "network-light") { + *size = requested_size; + return QIcon(":/icons/network-light").pixmap(requested_size); + } + return {}; } diff --git a/src/qml/res/icons/network-dark.png b/src/qml/res/icons/network-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5f9279247ddedf76008a2de81f43f88d60dff9b1 GIT binary patch literal 25693 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 oqiK3)G(*NFv!4q%F``ny|8&bWCj)tS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/qml/res/src/network-light.svg b/src/qml/res/src/network-light.svg new file mode 100644 index 0000000000..f798b6cb1d --- /dev/null +++ b/src/qml/res/src/network-light.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 49a742416dde17767f8199b84c63fe60aa1d50fa Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 14 Aug 2022 01:30:53 -0400 Subject: [PATCH 242/979] qml: use static backup for lottie network element Rebased-From: 88f9df422f18b71f4035c41e8e96cc698af1990a Github-Pull: bitcoin-core/gui-qml#157 --- src/qml/controls/Theme.qml | 1 + src/qml/pages/onboarding/onboarding02.qml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index c4bc93c149..e391bbdfb0 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -24,6 +24,7 @@ QtObject { } property QtObject image: QtObject { property url blocktime: dark ? "image://images/blocktime-dark" : "image://images/blocktime-light" + property url network: dark ? "image://images/network-dark" : "image://images/network-light" } function toggleDark() { dark = !dark diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 7e8855085b..47a154d0b2 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: "image://images/app" + source: Theme.image.network sourceSize.width: 200 sourceSize.height: 200 } From 36743212dacb134bac1a2ad057bbf20156b95292 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 15 Aug 2022 13:10:00 -0400 Subject: [PATCH 243/979] qml: out with the stub in with the main Does away with the stub file and rename it main.qml Rebased-From: 447fd0e459fe750f422b03138f24cd4de8a0b61f Github-Pull: bitcoin-core/gui-qml#160 --- src/qml/bitcoin.cpp | 2 +- src/qml/bitcoin_qml.qrc | 2 +- src/qml/pages/{stub.qml => main.qml} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/qml/pages/{stub.qml => main.qml} (100%) diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index c2475e13d8..e851755b98 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -184,7 +184,7 @@ int QmlGuiMain(int argc, char* argv[]) engine.rootContext()->setContextProperty("nodeModel", &node_model); - engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml"))); if (engine.rootObjects().isEmpty()) { return EXIT_FAILURE; } diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index f063c09130..35a25ff892 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -25,6 +25,7 @@ controls/ValueInput.qml controls/Wizard.qml pages/initerrormessage.qml + pages/main.qml pages/onboarding/onboarding01.qml pages/onboarding/onboarding01a.qml pages/onboarding/onboarding01b.qml @@ -38,7 +39,6 @@ pages/onboarding/onboarding06.qml pages/onboarding/onboarding06a.qml pages/onboarding/onboarding06b.qml - pages/stub.qml res/icons/arrow-down.png diff --git a/src/qml/pages/stub.qml b/src/qml/pages/main.qml similarity index 100% rename from src/qml/pages/stub.qml rename to src/qml/pages/main.qml From df683f9c7908eb982b0066d2e6186a3853597053 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Sun, 21 Aug 2022 18:29:58 -0400 Subject: [PATCH 244/979] qml: reduce usage of ternaries in Theme file Reduces usage of ternaries in Theme.qml by abstracting definitions of colors and images into "Sets" and using the definitions from the appropriate set for the current dark mode setting. Rebased-From: 6e0ee8003a45b430a0df6994522850e45c8f7894 Github-Pull: bitcoin-core/gui-qml#168 --- src/qml/bitcoin_qml.qrc | 1 - src/qml/controls/OutlineButton.qml | 29 -------- src/qml/controls/Theme.qml | 104 +++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 52 deletions(-) delete mode 100644 src/qml/controls/OutlineButton.qml diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index a5e01656f7..35a25ff892 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -17,7 +17,6 @@ controls/OnboardingNav.qml controls/OptionButton.qml controls/OptionSwitch.qml - controls/OutlineButton.qml controls/ProgressIndicator.qml controls/qmldir controls/Setting.qml diff --git a/src/qml/controls/OutlineButton.qml b/src/qml/controls/OutlineButton.qml deleted file mode 100644 index 10ce359d88..0000000000 --- a/src/qml/controls/OutlineButton.qml +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Button { - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - contentItem: Text { - text: parent.text - font: parent.font - color: Theme.color.neutral9 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - background: Rectangle { - implicitHeight: 46 - implicitWidth: 340 - color: Theme.color.background - radius: 5 - border { - width: 1 - color: Theme.color.neutral4 - } - } -} diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index e391bbdfb0..a88ebcaa26 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -1,31 +1,91 @@ pragma Singleton import QtQuick 2.15 +import QtQuick.Controls 2.15 -QtObject { +Control { property bool dark: true - property QtObject color: QtObject { - property color white: "#FFFFFF" - property color background: dark ? "black" : "white" - property color orange: dark ? "#F89B2A" : "#F7931A" - property color red: dark ? "#EC6363" : "#EB5757" - property color green: dark ? "#36B46B" : "#27AE60" - property color blue: dark ? "#3CA3DE" : "#2D9CDB" - property color purple: dark ? "#C075DC" : "#BB6BD9" - property color neutral0: dark ? "#000000" : "#FFFFFF" - property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" - property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" - property color neutral3: dark ? "#444444" : "#EDEDED" - property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" - property color neutral5: dark ? "#787878" : "#BBBBBB" - property color neutral6: dark ? "#949494" : "#999999" - property color neutral7: dark ? "#B0B0B0" : "#777777" - property color neutral8: dark ? "#CCCCCC" : "#404040" - property color neutral9: dark ? "#FFFFFF" : "#000000" + readonly property ColorSet color: dark ? darkColorSet : lightColorSet + readonly property ImageSet image: dark ? darkImageSet : lightImageSet + + component ColorSet: QtObject { + required property color white + required property color background + required property color orange + required property color red + required property color green + required property color blue + required property color purple + required property color neutral0 + required property color neutral1 + required property color neutral2 + required property color neutral3 + required property color neutral4 + required property color neutral5 + required property color neutral6 + required property color neutral7 + required property color neutral8 + required property color neutral9 + } + + component ImageSet: QtObject { + required property url blocktime + required property url network } - property QtObject image: QtObject { - property url blocktime: dark ? "image://images/blocktime-dark" : "image://images/blocktime-light" - property url network: dark ? "image://images/network-dark" : "image://images/network-light" + + ColorSet { + id: darkColorSet + white: "#FFFFFF" + background: "black" + orange: "#F89B2A" + red: "#EC6363" + green: "#36B46B" + blue: "#3CA3DE" + purple: "#C075DC" + neutral0: "#000000" + neutral1: "#1A1A1A" + neutral2: "#2D2D2D" + neutral3: "#444444" + neutral4: "#5C5C5C" + neutral5: "#787878" + neutral6: "#949494" + neutral7: "#B0B0B0" + neutral8: "#CCCCCC" + neutral9: "#FFFFFF" + } + + ColorSet { + id: lightColorSet + white: "#FFFFFF" + background: "white" + orange: "#F7931A" + red: "#EB5757" + green: "#27AE60" + blue: "#2D9CDB" + purple: "#BB6BD9" + neutral0: "#FFFFFF" + neutral1: "#F8F8F8" + neutral2: "#F4F4F4" + neutral3: "#EDEDED" + neutral4: "#DEDEDE" + neutral5: "#BBBBBB" + neutral6: "#999999" + neutral7: "#777777" + neutral8: "#404040" + neutral9: "#000000" } + + ImageSet { + id: darkImageSet + blocktime: "image://images/blocktime-dark" + network: "image://images/network-dark" + } + + ImageSet { + id: lightImageSet + blocktime: "image://images/blocktime-light" + network: "image://images/network-light" + } + function toggleDark() { dark = !dark } From 9fa368fd68f6a71455af23eb70981eea57fc8d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Thu, 8 Sep 2022 14:38:04 +0100 Subject: [PATCH 245/979] qml: split background and indicator on option switch Rebased-From: c50e6bc3ac822306bbae84c69fcc059bb20f59bd Github-Pull: bitcoin-core/gui-qml#169 --- src/qml/bitcoin.cpp | 2 +- src/qml/bitcoin_qml.qrc | 8 +- src/qml/controls/OptionSwitch.qml | 30 ++++--- src/qml/controls/OutlineButton.qml | 29 ------ src/qml/controls/Theme.qml | 102 ++++------------------ src/qml/imageprovider.cpp | 25 ------ src/qml/pages/onboarding/onboarding02.qml | 2 +- src/qml/pages/onboarding/onboarding03.qml | 2 +- src/qml/pages/{main.qml => stub.qml} | 0 src/qml/res/icons/blocktime-dark.png | Bin 19467 -> 0 bytes src/qml/res/icons/blocktime-light.png | Bin 18448 -> 0 bytes src/qml/res/icons/cross.png | Bin 538 -> 0 bytes src/qml/res/icons/network-dark.png | Bin 25693 -> 0 bytes src/qml/res/icons/network-light.png | Bin 26290 -> 0 bytes src/qml/res/src/blocktime-dark.svg | 55 ------------ src/qml/res/src/blocktime-light.svg | 60 ------------- src/qml/res/src/cross.svg | 4 - src/qml/res/src/network-dark.svg | 48 ---------- src/qml/res/src/network-light.svg | 48 ---------- 19 files changed, 39 insertions(+), 376 deletions(-) delete mode 100644 src/qml/controls/OutlineButton.qml rename src/qml/pages/{main.qml => stub.qml} (100%) delete mode 100644 src/qml/res/icons/blocktime-dark.png delete mode 100644 src/qml/res/icons/blocktime-light.png delete mode 100644 src/qml/res/icons/cross.png delete mode 100644 src/qml/res/icons/network-dark.png delete mode 100644 src/qml/res/icons/network-light.png delete mode 100644 src/qml/res/src/blocktime-dark.svg delete mode 100644 src/qml/res/src/blocktime-light.svg delete mode 100644 src/qml/res/src/cross.svg delete mode 100644 src/qml/res/src/network-dark.svg delete mode 100644 src/qml/res/src/network-light.svg diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index e851755b98..c2475e13d8 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -184,7 +184,7 @@ int QmlGuiMain(int argc, char* argv[]) engine.rootContext()->setContextProperty("nodeModel", &node_model); - engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml"))); + engine.load(QUrl(QStringLiteral("qrc:///qml/pages/stub.qml"))); if (engine.rootObjects().isEmpty()) { return EXIT_FAILURE; } diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index a5e01656f7..3d43f25d04 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -17,7 +17,6 @@ controls/OnboardingNav.qml controls/OptionButton.qml controls/OptionSwitch.qml - controls/OutlineButton.qml controls/ProgressIndicator.qml controls/qmldir controls/Setting.qml @@ -26,7 +25,6 @@ controls/ValueInput.qml controls/Wizard.qml pages/initerrormessage.qml - pages/main.qml pages/onboarding/onboarding01.qml pages/onboarding/onboarding01a.qml pages/onboarding/onboarding01b.qml @@ -40,21 +38,17 @@ pages/onboarding/onboarding06.qml pages/onboarding/onboarding06a.qml pages/onboarding/onboarding06b.qml + pages/stub.qml res/icons/arrow-down.png res/icons/arrow-up.png - res/icons/blocktime-dark.png - res/icons/blocktime-light.png ../qt/res/icons/bitcoin.png res/icons/caret-left.png res/icons/caret-right.png - res/icons/cross.png res/icons/export.png res/icons/gear.png res/icons/info.png - res/icons/network-dark.png - res/icons/network-light.png res/fonts/Inter-Regular.otf diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index b54660c276..32d09af2fd 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -7,21 +7,23 @@ import QtQuick.Controls 2.15 Switch { id: root - indicator: Rectangle { - implicitWidth: 45 - implicitHeight: 28 - x: root.leftPadding - y: Math.round((parent.height - height) / 2) - radius: 18 + implicitWidth: 45 + implicitHeight: 28 + background: Rectangle { + radius: Math.floor(height / 2) color: root.checked ? Theme.color.orange : Theme.color.neutral4 - Rectangle { - id: indicatorButton - y: parent.height / 2 - height / 2 - x: root.checked ? parent.width - width - 4 : 0 + 4 - width: 20 - height: 20 - radius: 18 - color: Theme.color.white + } + indicator: Rectangle { + property real _margin: Math.round((parent.height - height) / 2) + y: Math.round(parent.height - height) / 2 + x: root.checked ? parent.width - width - _margin : _margin + radius: 10 + width: 20 + height: 20 + color: Theme.color.white + Behavior on x { + SmoothedAnimation { + } } } } diff --git a/src/qml/controls/OutlineButton.qml b/src/qml/controls/OutlineButton.qml deleted file mode 100644 index 10ce359d88..0000000000 --- a/src/qml/controls/OutlineButton.qml +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Button { - font.family: "Inter" - font.styleName: "Semi Bold" - font.pixelSize: 18 - contentItem: Text { - text: parent.text - font: parent.font - color: Theme.color.neutral9 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - background: Rectangle { - implicitHeight: 46 - implicitWidth: 340 - color: Theme.color.background - radius: 5 - border { - width: 1 - color: Theme.color.neutral4 - } - } -} diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index a88ebcaa26..bfd98a119a 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -1,91 +1,27 @@ pragma Singleton import QtQuick 2.15 -import QtQuick.Controls 2.15 -Control { +QtObject { property bool dark: true - readonly property ColorSet color: dark ? darkColorSet : lightColorSet - readonly property ImageSet image: dark ? darkImageSet : lightImageSet - - component ColorSet: QtObject { - required property color white - required property color background - required property color orange - required property color red - required property color green - required property color blue - required property color purple - required property color neutral0 - required property color neutral1 - required property color neutral2 - required property color neutral3 - required property color neutral4 - required property color neutral5 - required property color neutral6 - required property color neutral7 - required property color neutral8 - required property color neutral9 - } - - component ImageSet: QtObject { - required property url blocktime - required property url network - } - - ColorSet { - id: darkColorSet - white: "#FFFFFF" - background: "black" - orange: "#F89B2A" - red: "#EC6363" - green: "#36B46B" - blue: "#3CA3DE" - purple: "#C075DC" - neutral0: "#000000" - neutral1: "#1A1A1A" - neutral2: "#2D2D2D" - neutral3: "#444444" - neutral4: "#5C5C5C" - neutral5: "#787878" - neutral6: "#949494" - neutral7: "#B0B0B0" - neutral8: "#CCCCCC" - neutral9: "#FFFFFF" - } - - ColorSet { - id: lightColorSet - white: "#FFFFFF" - background: "white" - orange: "#F7931A" - red: "#EB5757" - green: "#27AE60" - blue: "#2D9CDB" - purple: "#BB6BD9" - neutral0: "#FFFFFF" - neutral1: "#F8F8F8" - neutral2: "#F4F4F4" - neutral3: "#EDEDED" - neutral4: "#DEDEDE" - neutral5: "#BBBBBB" - neutral6: "#999999" - neutral7: "#777777" - neutral8: "#404040" - neutral9: "#000000" - } - - ImageSet { - id: darkImageSet - blocktime: "image://images/blocktime-dark" - network: "image://images/network-dark" + property QtObject color: QtObject { + property color white: "#FFFFFF" + property color background: dark ? "black" : "white" + property color orange: dark ? "#F89B2A" : "#F7931A" + property color red: dark ? "#EC6363" : "#EB5757" + property color green: dark ? "#36B46B" : "#27AE60" + property color blue: dark ? "#3CA3DE" : "#2D9CDB" + property color purple: dark ? "#C075DC" : "#BB6BD9" + property color neutral0: dark ? "#000000" : "#FFFFFF" + property color neutral1: dark ? "#1A1A1A" : "#F8F8F8" + property color neutral2: dark ? "#2D2D2D" : "#F4F4F4" + property color neutral3: dark ? "#444444" : "#EDEDED" + property color neutral4: dark ? "#5C5C5C" : "#DEDEDE" + property color neutral5: dark ? "#787878" : "#BBBBBB" + property color neutral6: dark ? "#949494" : "#999999" + property color neutral7: dark ? "#B0B0B0" : "#777777" + property color neutral8: dark ? "#CCCCCC" : "#404040" + property color neutral9: dark ? "#FFFFFF" : "#000000" } - - ImageSet { - id: lightImageSet - blocktime: "image://images/blocktime-light" - network: "image://images/network-light" - } - function toggleDark() { dark = !dark } diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index e690f84aa6..bbb294c0b3 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,16 +32,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/arrow-up").pixmap(requested_size); } - if (id == "blocktime-dark") { - *size = requested_size; - return QIcon(":/icons/blocktime-dark").pixmap(requested_size); - } - - if (id == "blocktime-light") { - *size = requested_size; - return QIcon(":/icons/blocktime-light").pixmap(requested_size); - } - if (id == "app") { *size = requested_size; return m_network_style->getAppIcon().pixmap(requested_size); @@ -57,11 +47,6 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/caret-right").pixmap(requested_size); } - if (id == "cross") { - *size = requested_size; - return QIcon(":/icons/cross").pixmap(requested_size); - } - if (id == "export") { *size = requested_size; return QIcon(":/icons/export").pixmap(requested_size); @@ -77,15 +62,5 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/info").pixmap(requested_size); } - if (id == "network-dark") { - *size = requested_size; - return QIcon(":/icons/network-dark").pixmap(requested_size); - } - - if (id == "network-light") { - *size = requested_size; - return QIcon(":/icons/network-light").pixmap(requested_size); - } - return {}; } diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index 47a154d0b2..7e8855085b 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: Theme.image.network + source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 8b81ea184b..39e4eaf1f1 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -22,7 +22,7 @@ Page { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { - source: Theme.image.blocktime + source: "image://images/app" sourceSize.width: 200 sourceSize.height: 200 } diff --git a/src/qml/pages/main.qml b/src/qml/pages/stub.qml similarity index 100% rename from src/qml/pages/main.qml rename to src/qml/pages/stub.qml diff --git a/src/qml/res/icons/blocktime-dark.png b/src/qml/res/icons/blocktime-dark.png deleted file mode 100644 index 2e34d95b4f79cd4a495bae0bb15c940bf231be6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19467 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 diff --git a/src/qml/res/icons/blocktime-light.png b/src/qml/res/icons/blocktime-light.png deleted file mode 100644 index ead9b4dd75071281ba3690134a3a422828a3a5fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18448 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 Hu0mjf3yUV) diff --git a/src/qml/res/icons/cross.png b/src/qml/res/icons/cross.png deleted file mode 100644 index 16d43af5332a8e3d76f030243107a9f9fd01811f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fh2BjaSW+oe0yhOu1KJW+e7=U z0wRqEJopL?ZZn*9ROHyk`u#xzi{N1=hTYj_N2P>X4oIE8`CIMBd69zBzI!R(_u4pU zE}atOg-q-@VYd6trn5Wep$O5wTL&q z@44ZmhTi7=#(%xrHlNNB(s^Q8)Th)$MK_wh?vHC|uNxyR1;!PiWt_5MIz zvmQ*DA9r63W}cn*gRhQFvt9oRUu2KDC!HYNe)C;Jv>MFV?VNl5X`1UbUbjzU>NZ<_ z$v+8XvBRs&EOGOJW|$zGex6u20euo*-;}Ps%c}ZJYpwl(_<8$I73{me++XOPv_-kmg|z|7S}|aRo2@7NlTD3?s@XQr@8ao3MQ_;lXlMZLOgGJ<(zip eXaL8`AGTldhu1O`Ot=D!a|TaWKbLh*2~7YhwhFue diff --git a/src/qml/res/icons/network-dark.png b/src/qml/res/icons/network-dark.png deleted file mode 100644 index 5f9279247ddedf76008a2de81f43f88d60dff9b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25693 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 oqiK3)G(*NFv!4q%F``ny|8&bWCj)tS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/blocktime-light.svg b/src/qml/res/src/blocktime-light.svg deleted file mode 100644 index 13de838d92..0000000000 --- a/src/qml/res/src/blocktime-light.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/cross.svg b/src/qml/res/src/cross.svg deleted file mode 100644 index 1fcfaf2d03..0000000000 --- a/src/qml/res/src/cross.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/qml/res/src/network-dark.svg b/src/qml/res/src/network-dark.svg deleted file mode 100644 index cee25614f8..0000000000 --- a/src/qml/res/src/network-dark.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/qml/res/src/network-light.svg b/src/qml/res/src/network-light.svg deleted file mode 100644 index f798b6cb1d..0000000000 --- a/src/qml/res/src/network-light.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1452beb0e556dbe2df935121cfe786f8f8d3aa6c Mon Sep 17 00:00:00 2001 From: Johnny Carlson Date: Sat, 17 Sep 2022 10:00:51 -0400 Subject: [PATCH 246/979] qml: fix Bitcoin icon size to match spec Rebased-From: 825451b9879a12774d12f13a1389e29b3568f4cc Github-Pull: bitcoin-core/gui-qml#172 --- src/qml/controls/OptionSwitch.qml | 30 ++++++++++------------ src/qml/pages/onboarding/onboarding01a.qml | 5 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/qml/controls/OptionSwitch.qml b/src/qml/controls/OptionSwitch.qml index 32d09af2fd..b54660c276 100644 --- a/src/qml/controls/OptionSwitch.qml +++ b/src/qml/controls/OptionSwitch.qml @@ -7,23 +7,21 @@ import QtQuick.Controls 2.15 Switch { id: root - implicitWidth: 45 - implicitHeight: 28 - background: Rectangle { - radius: Math.floor(height / 2) - color: root.checked ? Theme.color.orange : Theme.color.neutral4 - } indicator: Rectangle { - property real _margin: Math.round((parent.height - height) / 2) - y: Math.round(parent.height - height) / 2 - x: root.checked ? parent.width - width - _margin : _margin - radius: 10 - width: 20 - height: 20 - color: Theme.color.white - Behavior on x { - SmoothedAnimation { - } + implicitWidth: 45 + implicitHeight: 28 + x: root.leftPadding + y: Math.round((parent.height - height) / 2) + radius: 18 + color: root.checked ? Theme.color.orange : Theme.color.neutral4 + Rectangle { + id: indicatorButton + y: parent.height / 2 - height / 2 + x: root.checked ? parent.width - width - 4 : 0 + 4 + width: 20 + height: 20 + radius: 18 + color: Theme.color.white } } } diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index 24ac137e91..71de5a8b9e 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -32,8 +32,9 @@ Page { Layout.fillWidth: true Layout.alignment: Qt.AlignCenter source: "image://images/app" - sourceSize.width: 100 - sourceSize.height: 100 + // Bitcoin icon has ~11% padding + sourceSize.width: 112 + sourceSize.height: 112 } bannerMargin: 0 bold: true From 105b2281102dd38df7ddf3e612b86a995703bdc4 Mon Sep 17 00:00:00 2001 From: Jarol Rodriguez Date: Mon, 26 Sep 2022 00:50:30 -0400 Subject: [PATCH 247/979] qml: introduce bitcoin-circle icon Rebased-From: b09bc584bb0172c44376a7af09f877f07110199f Github-Pull: bitcoin-core/gui-qml#176 --- src/qml/appmode.h | 49 ---------------- src/qml/bitcoin.cpp | 9 --- src/qml/bitcoin_qml.qrc | 3 +- src/qml/components/ConnectionSettings.qml | 32 ++++++++--- src/qml/components/DeveloperOptions.qml | 24 ++++++-- src/qml/components/StorageLocations.qml | 8 +-- src/qml/components/StorageOptions.qml | 2 +- src/qml/components/StorageSettings.qml | 10 +++- src/qml/controls/Header.qml | 3 + src/qml/controls/OnboardingInfo.qml | 49 +++------------- src/qml/controls/Theme.qml | 3 - src/qml/imageprovider.cpp | 15 ++--- src/qml/pages/onboarding/onboarding01a.qml | 2 +- src/qml/pages/onboarding/onboarding02.qml | 22 +++---- src/qml/pages/onboarding/onboarding03.qml | 2 +- src/qml/pages/onboarding/onboarding04.qml | 45 +++------------ src/qml/pages/onboarding/onboarding05a.qml | 43 ++------------ src/qml/pages/onboarding/onboarding06a.qml | 64 +++++---------------- src/qml/res/icons/bitcoin-circle.png | Bin 0 -> 1742 bytes src/qml/res/icons/storage-dark.png | Bin 8412 -> 0 bytes src/qml/res/icons/storage-light.png | Bin 8693 -> 0 bytes src/qml/res/src/bitcoin-circle.svg | 4 ++ src/qml/res/src/storage-dark.svg | 21 ------- src/qml/res/src/storage-light.svg | 21 ------- 24 files changed, 118 insertions(+), 313 deletions(-) delete mode 100644 src/qml/appmode.h create mode 100644 src/qml/res/icons/bitcoin-circle.png delete mode 100644 src/qml/res/icons/storage-dark.png delete mode 100644 src/qml/res/icons/storage-light.png create mode 100644 src/qml/res/src/bitcoin-circle.svg delete mode 100644 src/qml/res/src/storage-dark.svg delete mode 100644 src/qml/res/src/storage-light.svg diff --git a/src/qml/appmode.h b/src/qml/appmode.h deleted file mode 100644 index 8265984103..0000000000 --- a/src/qml/appmode.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2022 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QML_APPMODE_H -#define BITCOIN_QML_APPMODE_H - -#include - -class AppMode : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool isDesktop READ isDesktop NOTIFY modeChanged) - Q_PROPERTY(bool isMobile READ isMobile NOTIFY modeChanged) - Q_PROPERTY(QString state READ state NOTIFY modeChanged) - -public: - enum Mode { - DESKTOP, - MOBILE - }; - - explicit AppMode(Mode mode) : m_mode(mode) - { - } - - bool isMobile() { return m_mode == MOBILE; } - bool isDesktop() { return m_mode == DESKTOP; } - QString state() - { - switch (m_mode) { - case MOBILE: - return "MOBILE"; - case DESKTOP: - return "DESKTOP"; - default: - return "DESKTOP"; - } - } - Mode mode() const { return m_mode; } - -Q_SIGNALS: - void modeChanged(); - -private: - const Mode m_mode; -}; - -#endif // BITCOIN_QML_APPMODE_H diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index 489171d3ed..e851755b98 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -185,14 +184,6 @@ int QmlGuiMain(int argc, char* argv[]) engine.rootContext()->setContextProperty("nodeModel", &node_model); -#ifdef __ANDROID__ - AppMode app_mode(AppMode::MOBILE); -#else - AppMode app_mode(AppMode::DESKTOP); -#endif // __ANDROID__ - - qmlRegisterSingletonInstance("org.bitcoincore.qt", 1, 0, "AppMode", &app_mode); - engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml"))); if (engine.rootObjects().isEmpty()) { return EXIT_FAILURE; diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc index 60d9abd540..d3210f9169 100644 --- a/src/qml/bitcoin_qml.qrc +++ b/src/qml/bitcoin_qml.qrc @@ -44,6 +44,7 @@ res/icons/arrow-down.png res/icons/arrow-up.png + res/icons/bitcoin-circle.png res/icons/blocktime-dark.png res/icons/blocktime-light.png ../qt/res/icons/bitcoin.png @@ -55,8 +56,6 @@ res/icons/info.png res/icons/network-dark.png res/icons/network-light.png - res/icons/storage-dark.png - res/icons/storage-light.png res/fonts/Inter-Regular.otf diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml index 38ed17d4f5..6553b32d8b 100644 --- a/src/qml/components/ConnectionSettings.qml +++ b/src/qml/components/ConnectionSettings.qml @@ -11,25 +11,43 @@ ColumnLayout { spacing: 20 Setting { Layout.fillWidth: true - header: qsTr("Enable listening") - description: qsTr("Allows incoming connections") - actionItem: OptionSwitch {} + header: qsTr("Use cellular data") + actionItem: OptionSwitch{} } Setting { Layout.fillWidth: true - header: qsTr("Map port using UPnP") - actionItem: OptionSwitch {} + header: qsTr("Daily upload limit") + actionItem: ValueInput { + description: qsTr("250 MB") + } } Setting { Layout.fillWidth: true - header: qsTr("Map port using NAT-PMP") + header: qsTr("Connection limit") + actionItem: ValueInput { + description: qsTr("6") + } + } + Setting { + Layout.fillWidth: true + header: qsTr("Enable listening") + description: qsTr("Increases data usage") actionItem: OptionSwitch {} } Setting { Layout.fillWidth: true - header: qsTr("Enable RPC server") + header: qsTr("Blocks Only") + description: qsTr("Reduces data usage.") actionItem: OptionSwitch {} } + Setting { + Layout.fillWidth: true + header: qsTr("Networks") + description: qsTr("Which networks to use for communication") + actionItem: ValueInput { + description: qsTr("6") + } + } Setting { last: true Layout.fillWidth: true diff --git a/src/qml/components/DeveloperOptions.qml b/src/qml/components/DeveloperOptions.qml index f876be549f..aec2f36a76 100644 --- a/src/qml/components/DeveloperOptions.qml +++ b/src/qml/components/DeveloperOptions.qml @@ -19,16 +19,14 @@ ColumnLayout { } Setting { Layout.fillWidth: true - header: qsTr("Database cache size") - actionItem: ValueInput { - description: ("450 MiB") - } + header: qsTr("Storage limit") + actionItem: OptionSwitch {} } Setting { Layout.fillWidth: true - header: qsTr("Script verification threads") + header: qsTr("Network") actionItem: ValueInput { - description: ("0") + description: qsTr("Mainnet") } } Setting { @@ -39,4 +37,18 @@ ColumnLayout { onToggled: Theme.toggleDark() } } + Setting { + Layout.fillWidth: true + header: qsTr("Other option...") + actionItem: ValueInput { + description: qsTr("42") + } + } + Setting { + Layout.fillWidth: true + header: qsTr("Other option...") + actionItem: ValueInput { + description: qsTr("Description...") + } + } } diff --git a/src/qml/components/StorageLocations.qml b/src/qml/components/StorageLocations.qml index 4bcb9e0b04..6eeda83440 100644 --- a/src/qml/components/StorageLocations.qml +++ b/src/qml/components/StorageLocations.qml @@ -14,14 +14,14 @@ ColumnLayout { spacing: 15 OptionButton { ButtonGroup.group: group - text: qsTr("Default directory") - description: qsTr("The downloaded block data will be saved to the default data directory for your OS.") + text: qsTr("SD Card") + description: qsTr("The available space is large enough for full block storage. ") recommended: true checked: true } OptionButton { ButtonGroup.group: group - text: qsTr("Custom directory") - description: qsTr("The downloaded block data will be saved to the chosen directory.") + text: qsTr("Hard drive") + description: qsTr("Available space only allows for partial block storage.") } } diff --git a/src/qml/components/StorageOptions.qml b/src/qml/components/StorageOptions.qml index 0c0e4dc115..d3f3a745ce 100644 --- a/src/qml/components/StorageOptions.qml +++ b/src/qml/components/StorageOptions.qml @@ -15,7 +15,7 @@ ColumnLayout { OptionButton { ButtonGroup.group: group text: qsTr("Reduce storage") - description: qsTr("Uses about 2GB.") + description: qsTr("Uses about 75GB.") recommended: true checked: true detail: ProgressIndicator { diff --git a/src/qml/components/StorageSettings.qml b/src/qml/components/StorageSettings.qml index 90c16f38dd..0ef026f1b4 100644 --- a/src/qml/components/StorageSettings.qml +++ b/src/qml/components/StorageSettings.qml @@ -18,7 +18,7 @@ ColumnLayout { Layout.fillWidth: true header: qsTr("Storage limit") actionItem: ValueInput { - description: qsTr("2 GB") + description: qsTr("75 GB") } } Setting { @@ -27,5 +27,13 @@ ColumnLayout { actionItem: ValueInput { description: qsTr("c://.../data") } + + } + Setting { + Layout.fillWidth: true + header: qsTr("Block location") + actionItem: ValueInput { + description: qsTr("c://.../blocks") + } } } diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml index e752115524..913020a84e 100644 --- a/src/qml/controls/Header.qml +++ b/src/qml/controls/Header.qml @@ -24,6 +24,7 @@ Control { spacing: 0 Label { Layout.fillWidth: true + Layout.preferredWidth: 0 topPadding: root.headerMargin font.family: "Inter" font.styleName: root.bold ? "Semi Bold" : "Regular" @@ -35,6 +36,7 @@ Control { } Loader { Layout.fillWidth: true + Layout.preferredWidth: 0 active: root.description.length > 0 visible: active sourceComponent: Label { @@ -50,6 +52,7 @@ Control { } Loader { Layout.fillWidth: true + Layout.preferredWidth: 0 active: root.subtext.length > 0 visible: active sourceComponent: Label { diff --git a/src/qml/controls/OnboardingInfo.qml b/src/qml/controls/OnboardingInfo.qml index e73ebb5abd..5e490848f9 100644 --- a/src/qml/controls/OnboardingInfo.qml +++ b/src/qml/controls/OnboardingInfo.qml @@ -5,9 +5,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import org.bitcoincore.qt 1.0 -Item { +Control { id: root property alias banner: banner_loader.sourceComponent required property string buttonText @@ -26,10 +25,7 @@ Item { implicitWidth: 600 - ColumnLayout { - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width - id: information + contentItem: ColumnLayout { spacing: 0 Loader { id: banner_loader @@ -53,40 +49,11 @@ Item { subtextMargin: root.subtextMargin subtextSize: root.subtextSize } - } - ContinueButton { - id: continueButton - anchors.horizontalCenter: parent.horizontalCenter - anchors.topMargin: 40 - anchors.bottomMargin: 60 - anchors.leftMargin: 20 - anchors.rightMargin: 20 - text: root.buttonText - onClicked: swipeView.incrementCurrentIndex() - } - - state: AppMode.state - - states: [ - State { - name: "MOBILE" - AnchorChanges { - target: continueButton - anchors.top: undefined - anchors.bottom: continueButton.parent.bottom - anchors.right: continueButton.parent.right - anchors.left: continueButton.parent.left - } - }, - State { - name: "DESKTOP" - AnchorChanges { - target: continueButton - anchors.top: information.bottom - anchors.bottom: undefined - anchors.left: undefined - anchors.right: undefined - } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: root.buttonText + onClicked: swipeView.incrementCurrentIndex() } - ] + } } diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml index c85f18161c..a88ebcaa26 100644 --- a/src/qml/controls/Theme.qml +++ b/src/qml/controls/Theme.qml @@ -30,7 +30,6 @@ Control { component ImageSet: QtObject { required property url blocktime required property url network - required property url storage } ColorSet { @@ -79,14 +78,12 @@ Control { id: darkImageSet blocktime: "image://images/blocktime-dark" network: "image://images/network-dark" - storage: "image://images/storage-dark" } ImageSet { id: lightImageSet blocktime: "image://images/blocktime-light" network: "image://images/network-light" - storage: "image://images/storage-light" } function toggleDark() { diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp index 83ad5f53b4..36a7be9943 100644 --- a/src/qml/imageprovider.cpp +++ b/src/qml/imageprovider.cpp @@ -32,6 +32,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/arrow-up").pixmap(requested_size); } + if (id == "bitcoin-circle") { + *size = requested_size; + return QIcon(":/icons/bitcoin-circle").pixmap(requested_size); + } + if (id == "blocktime-dark") { *size = requested_size; return QIcon(":/icons/blocktime-dark").pixmap(requested_size); @@ -87,15 +92,5 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize return QIcon(":/icons/network-light").pixmap(requested_size); } - if (id == "storage-dark") { - *size = requested_size; - return QIcon(":/icons/storage-dark").pixmap(requested_size); - } - - if (id == "storage-light") { - *size = requested_size; - return QIcon(":/icons/storage-light").pixmap(requested_size); - } - return {}; } diff --git a/src/qml/pages/onboarding/onboarding01a.qml b/src/qml/pages/onboarding/onboarding01a.qml index a6fdfad23c..71de5a8b9e 100644 --- a/src/qml/pages/onboarding/onboarding01a.qml +++ b/src/qml/pages/onboarding/onboarding01a.qml @@ -26,7 +26,7 @@ Page { } } OnboardingInfo { - height: parent.height + anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { Layout.fillWidth: true diff --git a/src/qml/pages/onboarding/onboarding02.qml b/src/qml/pages/onboarding/onboarding02.qml index a0de44c794..47a154d0b2 100644 --- a/src/qml/pages/onboarding/onboarding02.qml +++ b/src/qml/pages/onboarding/onboarding02.qml @@ -19,16 +19,16 @@ Page { } } OnboardingInfo { - height: parent.height - anchors.horizontalCenter: parent.horizontalCenter - banner: Image { - source: Theme.image.network - sourceSize.width: 200 - sourceSize.height: 200 - } - bold: true - header: qsTr("Strengthen bitcoin") - description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") - buttonText: "Next" + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + banner: Image { + source: Theme.image.network + sourceSize.width: 200 + sourceSize.height: 200 + } + bold: true + header: qsTr("Strengthen bitcoin") + description: qsTr("Bitcoin Core runs a full Bitcoin node which verifies the rules of the network are being followed.\n\nUsers running nodes is what makes bitcoin\nso resilient and trustworthy.") + buttonText: "Next" } } diff --git a/src/qml/pages/onboarding/onboarding03.qml b/src/qml/pages/onboarding/onboarding03.qml index 4000d54f74..8b81ea184b 100644 --- a/src/qml/pages/onboarding/onboarding03.qml +++ b/src/qml/pages/onboarding/onboarding03.qml @@ -19,7 +19,7 @@ Page { } } OnboardingInfo { - height: parent.height + anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter banner: Image { source: Theme.image.blocktime diff --git a/src/qml/pages/onboarding/onboarding04.qml b/src/qml/pages/onboarding/onboarding04.qml index c5b0084882..259bc0f2d0 100644 --- a/src/qml/pages/onboarding/onboarding04.qml +++ b/src/qml/pages/onboarding/onboarding04.qml @@ -5,7 +5,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import org.bitcoincore.qt 1.0 import "../../controls" import "../../components" @@ -21,7 +20,6 @@ Page { } } ColumnLayout { - id: selections width: 600 spacing: 0 anchors.top: parent.top @@ -30,47 +28,18 @@ Page { Layout.fillWidth: true bold: true header: qsTr("Storage location") - description: qsTr("Where do you want to store the downloaded block data?") + description: qsTr("On which drive do you want to store the downloaded block data?") descriptionMargin: 20 } StorageLocations { Layout.topMargin: 30 Layout.alignment: Qt.AlignCenter } - } - ContinueButton { - id: continueButton - anchors.horizontalCenter: parent.horizontalCenter - anchors.topMargin: 40 - anchors.bottomMargin: 60 - anchors.rightMargin: 20 - anchors.leftMargin: 20 - text: "Next" - onClicked: swipeView.incrementCurrentIndex() - } - - state: AppMode.state - - states: [ - State { - name: "MOBILE" - AnchorChanges { - target: continueButton - anchors.top: undefined - anchors.bottom: continueButton.parent.bottom - anchors.left: continueButton.parent.left - anchors.right: continueButton.parent.right - } - }, - State { - name: "DESKTOP" - AnchorChanges { - target: continueButton - anchors.top: selections.bottom - anchors.bottom: undefined - anchors.left: undefined - anchors.right: undefined - } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() } - ] + } } diff --git a/src/qml/pages/onboarding/onboarding05a.qml b/src/qml/pages/onboarding/onboarding05a.qml index 11b773f16e..7dfc79c222 100644 --- a/src/qml/pages/onboarding/onboarding05a.qml +++ b/src/qml/pages/onboarding/onboarding05a.qml @@ -5,7 +5,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.11 -import org.bitcoincore.qt 1.0 import "../../controls" import "../../components" @@ -21,7 +20,6 @@ Page { } } ColumnLayout { - id: selections width: 600 spacing: 0 anchors.top: parent.top @@ -47,40 +45,11 @@ Page { swipeView.inSubPage = true } } - } - ContinueButton { - id: continueButton - anchors.topMargin: 40 - anchors.leftMargin: 20 - anchors.rightMargin: 20 - anchors.bottomMargin: 60 - anchors.horizontalCenter: parent.horizontalCenter - text: "Next" - onClicked: swipeView.incrementCurrentIndex() - } - - state: AppMode.state - - states: [ - State { - name: "MOBILE" - AnchorChanges { - target: continueButton - anchors.top: undefined - anchors.bottom: continueButton.parent.bottom - anchors.left: continueButton.parent.left - anchors.right: continueButton.parent.right - } - }, - State { - name: "DESKTOP" - AnchorChanges { - target: continueButton - anchors.top: selections.bottom - anchors.bottom: undefined - anchors.left: undefined - anchors.right: undefined - } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.incrementCurrentIndex() } - ] + } } diff --git a/src/qml/pages/onboarding/onboarding06a.qml b/src/qml/pages/onboarding/onboarding06a.qml index 4de26ceee5..00059d4b5d 100644 --- a/src/qml/pages/onboarding/onboarding06a.qml +++ b/src/qml/pages/onboarding/onboarding06a.qml @@ -5,7 +5,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import org.bitcoincore.qt 1.0 import "../../controls" import "../../components" @@ -21,71 +20,36 @@ Page { } } ColumnLayout { - id: selections width: 600 spacing: 0 anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter - Image { - Layout.topMargin: 20 - Layout.alignment: Qt.AlignCenter - source: Theme.image.storage - sourceSize.width: 200 - sourceSize.height: 200 - } Header { Layout.fillWidth: true bold: true - header: qsTr("Starting initial download") - headerMargin: 30 - description: qsTr("The application will connect to the Bitcoin network and start downloading and verifying transactions.\n\nThis may take several hours, or even days, based on your connection.") - descriptionMargin: 20 + header: qsTr("Connection") + description: qsTr("Communicating with the Bitcoin network can use a lot of data.") + } + ConnectionOptions { + Layout.topMargin: 30 + Layout.alignment: Qt.AlignCenter } TextButton { Layout.alignment: Qt.AlignCenter Layout.topMargin: 30 - text: "Connection settings" + text: "Detailed Settings" textSize: 18 - textColor: Theme.color.orange + textColor: "#F7931A" onClicked: { connections.incrementCurrentIndex() swipeView.inSubPage = true } } - } - ContinueButton { - id: continueButton - anchors.topMargin: 40 - anchors.leftMargin: 20 - anchors.rightMargin: 20 - anchors.bottomMargin: 60 - anchors.horizontalCenter: parent.horizontalCenter - text: "Next" - onClicked: swipeView.finished = true - } - - state: AppMode.state - - states: [ - State { - name: "MOBILE" - AnchorChanges { - target: continueButton - anchors.top: undefined - anchors.bottom: continueButton.parent.bottom - anchors.right: continueButton.parent.right - anchors.left: continueButton.parent.left - } - }, - State { - name: "DESKTOP" - AnchorChanges { - target: continueButton - anchors.top: selections.bottom - anchors.bottom: undefined - anchors.right: undefined - anchors.left: undefined - } + ContinueButton { + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 40 + text: "Next" + onClicked: swipeView.finished = true } - ] + } } diff --git a/src/qml/res/icons/bitcoin-circle.png b/src/qml/res/icons/bitcoin-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..dac55c361029b3302d7f55bbfe9fe94cad7e37d7 GIT binary patch literal 1742 zcmV;<1~K`GP)nv|HX;UXn6+OZkMg%Kw7%2w63&5oH(QNU$RJI@4doDk=%le$*k#nkd6jf#j;d#+^LI?*xCimrUr7;)XAtx~M&9>xulq51-$6Y0Bq8YR)1bE# zjyTJ6ue%vXj5?zMa(4o@ljkYV`&4ryKV)T#<*qc25W`oU5M}e&8gJ6v%R2p3 z%O4XEb-nTKVE%|0^$9*IXFZ~B1TFRE`&>^235rYdCSuS!()ea9g1*Cxjw@F%i9T$B zyBIGc293fuzem*lix@4{RO^vrjtr|h!C|VloamaKbVo(KYLlE>G(B>|u79q-(qE$_k@luRhJ^C?#&fY9koF`MuAj-y| zaXL#7<2IDSFW_Lzq&S~%lSQKa1vCUO3+Ttbw5|;O$F{M9Ki~bh*}?eUU|`e>B1aTm2XJo#<+%9= z64io8na3ruuUSlfKQPwjbpWUHaq}4x)sh&@^t>r~5aW1{H`%}V6~NPiC@eq>njZeL z_)-#V%HUQ{{q8`aq~UDvaeUFm$E)sB$R>LcH-{8=r93R{?C$-Q zygk^ALc4JpUm?Z~FP-D^qi~ct<4GPRZwXC&!S{KKC%BCVd5({mkEohPf`C+$H9i;6 z$>sWd0OEUDP9i{W8t(}_<}yMbh4|iU1Zqc5!;%ll`Z${u8tiDSSOkdb_KVg z$>s5aix6LHrW<}x>{r#Q_CJoI2y!5AnGt2*qan&C?pu`;6vIm&XeZM||xsqzK8r z)atjYcpLGt8ulhcm8>%UMt{J~R1jk!;#;dYo{*hKM)?;L-^y?f5$I1Ai9WLQBO*On zk3?LC{zT|(Rw5C$nhS_n1vN-S{fi2s$6oviiJ-~sM~O&s583FSOf6bnsYgPpjxLm- z?LvD(#hoZw6--6~Yz8M&;u4JHOC*54U^oe)7s=D=&S5A?+Lag=@d@h?W$XBui-^%q zr5VL<4A=LY_zfdT(*bO4^yKR0bU52m$w2O7Jbz*q^JySMh6d&{i$C!R_c4$Pwk1H8 kWm%SGS(as4mStK01~e>;3Rz|G2><{907*qoM6N<$f|y1-8UO$Q literal 0 HcmV?d00001 diff --git a/src/qml/res/icons/storage-dark.png b/src/qml/res/icons/storage-dark.png deleted file mode 100644 index 8490d579ad5d1a84e74d12af7b24c154f0c2af5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8412 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 diff --git a/src/qml/res/icons/storage-light.png b/src/qml/res/icons/storage-light.png deleted file mode 100644 index ab5700bad14d04f07c809d79edde4c5f55ddfaa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8693 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