From b35dda56ebd07d5f58be7552f6814965fffc091a Mon Sep 17 00:00:00 2001 From: Eduardo Gonzalez Lazo <30321688+EddyTheCo@users.noreply.github.com> Date: Sat, 9 Dec 2023 12:34:07 +0100 Subject: [PATCH] Improvements (#56) (#57) * Align the URI of the modules * Create alias targets * Set private the singleton constructor * Added the examples * Improve readmes --- .github/workflows/build-docs.yml | 4 +- .github/workflows/build-test-install.yml | 5 +- CMakeLists.txt | 43 ++- Config.cmake.in | 2 +- QrDec/CMakeLists.txt | 13 +- QrDec/Config.cmake.in | 3 - QrDec/README.md | 20 +- QrDec/tests/CMakeLists.txt | 15 -- QrDec/tests/load_from_file.cpp | 21 -- QrDec/tests/qrcode-feature.jpg | Bin 18976 -> 0 bytes QrGen/CMakeLists.txt | 18 +- QrGen/README.md | 14 +- QtQrDec/CMakeLists.txt | 132 +++++---- QtQrDec/Config.cmake.in | 3 - QtQrDec/Qrimagedecoder.cpp | 326 ++++++++++++----------- QtQrDec/README.md | 82 +++--- QtQrDec/examples/CMakeLists.txt | 68 +++++ QtQrDec/examples/qml/qrcam.qml | 72 +++++ QtQrDec/examples/qml/qrtext.qml | 37 +++ QtQrDec/examples/qrcam.cpp | 24 ++ QtQrDec/examples/qrtext.cpp | 24 ++ QtQrDec/frag/qrscanner.frag | 80 ++++++ QtQrDec/include/Qrimagedecoder.hpp | 31 ++- QtQrDec/qml/QrCam.qml | 30 +-- QtQrDec/qml/QrDecPop.qml | 41 +++ QtQrDec/qml/QrQmlCamera.qml | 31 --- QtQrDec/qml/QrTextCamPop.qml | 82 ------ QtQrDec/qml/QrTextField.qml | 50 ++++ QtQrGen/CMakeLists.txt | 129 ++++----- QtQrGen/Qrimageprovider.cpp | 11 +- QtQrGen/README.md | 77 +++--- QtQrGen/examples/CMakeLists.txt | 64 +++++ QtQrGen/examples/image.cpp | 23 ++ QtQrGen/examples/qml/image.qml | 40 +++ QtQrGen/examples/qml/text.qml | 40 +++ QtQrGen/examples/text.cpp | 23 ++ QtQrGen/frag/qrscanner.frag | 80 ++++++ QtQrGen/include/Qrimageprovider.hpp | 5 +- QtQrGen/qml/AddressQr.qml | 47 ---- QtQrGen/qml/PayQrPop.qml | 57 ---- QtQrGen/qml/QrGenImage.qml | 22 ++ QtQrGen/qml/QrGenPop.qml | 74 +++++ QtQrGen/qml/QrLabel.qml | 36 --- QtQrGen/qml/QrText.qml | 50 ++++ README.md | 22 +- 45 files changed, 1325 insertions(+), 746 deletions(-) delete mode 100644 QrDec/Config.cmake.in delete mode 100755 QrDec/tests/CMakeLists.txt delete mode 100644 QrDec/tests/load_from_file.cpp delete mode 100644 QrDec/tests/qrcode-feature.jpg delete mode 100644 QtQrDec/Config.cmake.in create mode 100644 QtQrDec/examples/CMakeLists.txt create mode 100644 QtQrDec/examples/qml/qrcam.qml create mode 100644 QtQrDec/examples/qml/qrtext.qml create mode 100644 QtQrDec/examples/qrcam.cpp create mode 100644 QtQrDec/examples/qrtext.cpp create mode 100644 QtQrDec/frag/qrscanner.frag create mode 100644 QtQrDec/qml/QrDecPop.qml delete mode 100644 QtQrDec/qml/QrQmlCamera.qml delete mode 100644 QtQrDec/qml/QrTextCamPop.qml create mode 100644 QtQrDec/qml/QrTextField.qml create mode 100644 QtQrGen/examples/CMakeLists.txt create mode 100644 QtQrGen/examples/image.cpp create mode 100644 QtQrGen/examples/qml/image.qml create mode 100644 QtQrGen/examples/qml/text.qml create mode 100644 QtQrGen/examples/text.cpp create mode 100644 QtQrGen/frag/qrscanner.frag delete mode 100644 QtQrGen/qml/AddressQr.qml delete mode 100644 QtQrGen/qml/PayQrPop.qml create mode 100644 QtQrGen/qml/QrGenImage.qml create mode 100644 QtQrGen/qml/QrGenPop.qml delete mode 100644 QtQrGen/qml/QrLabel.qml create mode 100644 QtQrGen/qml/QrText.qml diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 07714b0..37cf8e5 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -6,8 +6,8 @@ on: branches: [main] jobs: build_doxygen: - uses: EddyTheCo/Common/.github/workflows/build-docs.yml@main - if: ${{ (github.event.pull_request.merged == true) && (startsWith(github.base_ref, 'main')) }} + uses: EddyTheCo/Common/.github/workflows/build-docs.yml@v0.1.1 + if: ${{ (github.event.pull_request.merged == true) && (startsWith(github.base_ref, 'main')) }} permissions: pages: write id-token: write diff --git a/.github/workflows/build-test-install.yml b/.github/workflows/build-test-install.yml index e0ff548..d1570c9 100644 --- a/.github/workflows/build-test-install.yml +++ b/.github/workflows/build-test-install.yml @@ -13,14 +13,15 @@ jobs: matrix: os: [ubuntu-latest,macos-latest,windows-latest] - uses: EddyTheCo/Common/.github/workflows/build-test-install.yml@main + uses: EddyTheCo/Common/.github/workflows/build-test-install.yml@v0.1.1 permissions: contents: write with: os: ${{ matrix.os }} sharedLib: true qtVersion: '6.6.0' - qtModules: 'qtshadertools qtmultimedia' + qtModules: 'qtshadertools qtmultimedia' + test: false release: if: startsWith(github.ref, 'refs/tags/v') needs: build_test_package diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a50659..f5a7d87 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,16 +15,6 @@ version_from_git( ) project(qrCode VERSION ${VERSION} DESCRIPTION "library for qr code manipulation" LANGUAGES CXX) -set(default_build_type "Release") -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") -endif() - set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -32,39 +22,40 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) include(GNUInstallDirs) +add_subdirectory(QrDec) add_subdirectory(QrGen) +add_subdirectory(QtQrDec) add_subdirectory(QtQrGen) -add_subdirectory(QrDec) -add_subdirectory(QtQrDec) -install(EXPORT qrCodeTargets - FILE qrCodeTargets.cmake - NAMESPACE qrCode:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qrCode - COMPONENT qrCode +install(EXPORT ${PROJECT_NAME}-config + FILE ${PROJECT_NAME}-config.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Esterv + NAMESPACE ${PROJECT_NAME}:: + COMPONENT ${PROJECT_NAME} ) include(CMakePackageConfigHelpers) configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/qrCodeConfig.cmake" - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qrCode + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Esterv ) write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/qrCodeConfigVersion.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" VERSION ${VERSION} COMPATIBILITY SameMajorVersion ) install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/qrCodeConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/qrCodeConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/qrCode + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Esterv ) -export(EXPORT qrCodeTargets - FILE "${CMAKE_CURRENT_BINARY_DIR}/qrCodeTargets.cmake" +export(EXPORT ${PROJECT_NAME}-config + FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" ) + if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - set(CPACK_PACKAGE_CONTACT "estervtech") + set(CPACK_PACKAGE_CONTACT "estervtech") include(CTest) set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-v${SEMVER}-${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_VERSION}-${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_CXX_COMPILER_ID}") if(NOT BUILD_SHARED_LIBS) diff --git a/Config.cmake.in b/Config.cmake.in index 5083de2..b55dd42 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -2,5 +2,5 @@ include(CMakeFindDependencyMacro) find_dependency(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick Svg OPTIONAL_COMPONENTS Multimedia ) find_dependency(OpenCV REQUIRED COMPONENTS core objdetect ) -find_dependency(MyDesigns 0.4 REQUIRED CONFIG) +find_dependency(EstervDesigns 1.0 COMPONENTS SimpleStyle CustomControls CONFIG) include ( "${CMAKE_CURRENT_LIST_DIR}/qrCodeTargets.cmake" ) diff --git a/QrDec/CMakeLists.txt b/QrDec/CMakeLists.txt index 7a46843..9f0b506 100755 --- a/QrDec/CMakeLists.txt +++ b/QrDec/CMakeLists.txt @@ -47,20 +47,21 @@ endif() if(OpenCV_FOUND) add_library(QrDec qrcodedec.cpp) + add_library(${PROJECT_NAME}::QrDec ALIAS QrDec) target_include_directories(QrDec PUBLIC $) target_link_libraries(QrDec PUBLIC ${OpenCV_LIBS}) target_include_directories(QrDec PUBLIC $ - "$") + "$") install(TARGETS QrDec - EXPORT qrCodeTargets + EXPORT ${PROJECT_NAME}-config DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT Qr + COMPONENT QrDec ) install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qrCode - COMPONENT Qr + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Esterv/${PROJECT_NAME} + COMPONENT QrDec ) else() - message(STATUS "OpenCV was not found") + message(STATUS "The QRCODE decoding library will not be built") endif(OpenCV_FOUND) diff --git a/QrDec/Config.cmake.in b/QrDec/Config.cmake.in deleted file mode 100644 index c32b57b..0000000 --- a/QrDec/Config.cmake.in +++ /dev/null @@ -1,3 +0,0 @@ -@PACKAGE_INIT@ - -include ( "${CMAKE_CURRENT_LIST_DIR}/QrDecTargets.cmake" ) diff --git a/QrDec/README.md b/QrDec/README.md index 2b1763e..8a1a3ca 100644 --- a/QrDec/README.md +++ b/QrDec/README.md @@ -1,11 +1,21 @@ -# QrGen +# QrDec This repo detect and decode a Qr code in a image. -The compiled library depend on [opencv](https://opencv.org/) - -CMake produce the target 'QrDec' so one can link to this library like +The detection and decoding is performed by [OpenCV](https://opencv.org/) libraries. +In case OpenCV is not found on your system CMake will download pre compiled libraries from [my action releases](https://github.com/EddyTheCo/install-OpenCV-action). + +## Adding the libraries to your CMake project ``` -target_link_libraries( QrDec) +include(FetchContent) +FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 COMPONENTS QrDec CONFIG +) +FetchContent_MakeAvailable(qrCode) + +target_link_libraries( qrCode::QrDec) ``` diff --git a/QrDec/tests/CMakeLists.txt b/QrDec/tests/CMakeLists.txt deleted file mode 100755 index 6e31857..0000000 --- a/QrDec/tests/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.11 FATAL_ERROR) - -project(module_test VERSION 0.1 DESCRIPTION "diferent tests for the library" LANGUAGES CXX) - - - -add_executable(load_from_file load_from_file.cpp) -target_link_libraries(load_from_file PRIVATE QrDec) -add_test(NAME load_from_file COMMAND load_from_file ${CMAKE_CURRENT_BINARY_DIR}/qrcode-feature.jpg) - - -target_include_directories(load_from_file PRIVATE ${OpenCV_INCLUDE_DIRS}) -target_link_libraries(load_from_file PRIVATE ${OpenCV_LIBS}) -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/qrcode-feature.jpg - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/QrDec/tests/load_from_file.cpp b/QrDec/tests/load_from_file.cpp deleted file mode 100644 index e6fd009..0000000 --- a/QrDec/tests/load_from_file.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include"qrcodedec.hpp" -#include -#undef NDEBUG -#include - -using namespace qrcodedec; - -using namespace cv; - -int main(int argc, char** argv) -{ - Mat img = imread(argv[1]); - Mat gray; - - cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); - - assert(decode_grey(gray.data,gray.rows,gray.cols)=="http://LearnOpenCV.com"); - - return 0; - -} diff --git a/QrDec/tests/qrcode-feature.jpg b/QrDec/tests/qrcode-feature.jpg deleted file mode 100644 index f6601118db931e45d81402a7eceed6f765696086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18976 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 XiN_w8P4WVuh7<|_SfV|qy)6AN<)w5- diff --git a/QrGen/CMakeLists.txt b/QrGen/CMakeLists.txt index 2824ed0..7cd2870 100755 --- a/QrGen/CMakeLists.txt +++ b/QrGen/CMakeLists.txt @@ -1,23 +1,19 @@ add_library(QrGen src/qrcodegen.cpp src/utils.cpp) +add_library(${PROJECT_NAME}::QrGen ALIAS QrGen) set_target_properties(QrGen PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_compile_features(QrGen PUBLIC cxx_std_11) target_include_directories(QrGen PUBLIC $ - "$") + "$") -install(TARGETS QrGen - EXPORT qrCodeTargets +install(TARGETS QrGen + EXPORT ${PROJECT_NAME}-config DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT Qr + COMPONENT QrGen ) install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qrCode - COMPONENT Qr + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Esterv/${PROJECT_NAME} + COMPONENT QrGen ) -if(BUILD_DOCS) - get_target_property(build_docs cmake_build_docs SOURCES) - include(${build_docs}) -endif() diff --git a/QrGen/README.md b/QrGen/README.md index 304c388..897b479 100644 --- a/QrGen/README.md +++ b/QrGen/README.md @@ -1,9 +1,19 @@ # QrGen The code is based on [QR Code generator library](https://github.com/nayuki/QR-Code-generator) and produce a library for the generation of a QR code of certain data. -CMake produce the target 'QrGen' so one can link to this library like + +## Adding the libraries to your CMake project ``` -target_link_libraries( QrGen) +include(FetchContent) +FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 COMPONENTS QrGen CONFIG +) +FetchContent_MakeAvailable(qrCode) + +target_link_libraries( qrCode::QrGen) ``` diff --git a/QtQrDec/CMakeLists.txt b/QtQrDec/CMakeLists.txt index c8e3f36..6199552 100644 --- a/QtQrDec/CMakeLists.txt +++ b/QtQrDec/CMakeLists.txt @@ -1,51 +1,89 @@ -find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick OPTIONAL_COMPONENTS Multimedia) +if(EMSCRIPTEN) + find_package(Qt6 COMPONENTS Core Gui Qml Quick ShaderTools) +else() + find_package(Qt6 COMPONENTS Core Gui Qml Quick ShaderTools Multimedia) +endif(EMSCRIPTEN) + FetchContent_Declare( - MyDesigns - GIT_REPOSITORY https://github.com/EddyTheCo/MyDesigns.git - GIT_TAG v0.4.1 - FIND_PACKAGE_ARGS 0.4 CONFIG - ) -FetchContent_MakeAvailable(MyDesigns) + EstervDesigns + GIT_REPOSITORY https://github.com/EddyTheCo/MyDesigns.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 COMPONENTS SimpleStyle CustomControls CONFIG +) +FetchContent_MakeAvailable(EstervDesigns) + + if (Qt6_FOUND AND TARGET QrDec) - qt_standard_project_setup() - qt6_add_qml_module(QtQrDec - URI QtQrDec - VERSION 1.0 - SOURCES Qrimagedecoder.cpp include/Qrimagedecoder.hpp - QML_FILES - qml/QrQmlCamera.qml - qml/QrCam.qml - qml/QrTextCamPop.qml - RESOURCE_PREFIX - "/esterVtech.com/imports" - OUTPUT_TARGETS out_targets_var - OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/QtQrDec - IMPORT_PATH ${CMAKE_BINARY_DIR} - ) - - target_include_directories(QtQrDec PUBLIC $ - "$") - - target_link_libraries(QtQrDec PUBLIC Qt6::Gui Qt6::Quick QrDec $ MyDesigns - $<$,STATIC_LIBRARY>:MyDesignsplugin>) - - install(TARGETS QtQrDec QtQrDecplugin ${out_targets_var} - EXPORT qrCodeTargets - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT QtQr - ) - install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qrCode - COMPONENT QtQr - ) - install(DIRECTORY ${CMAKE_BINARY_DIR}/QtQrDec/ - DESTINATION ${CMAKE_INSTALL_LIBDIR}/QMLPlugins/QtQrDec - COMPONENT QtQr - ) - - if(EMSCRIPTEN) - target_compile_definitions(QtQrDec PRIVATE USE_EMSCRIPTEN) - endif(EMSCRIPTEN) + qt_standard_project_setup() + qt6_add_qml_module(QtQrDec + URI Esterv.CustomControls.QrDec + VERSION 1.0 + SOURCES Qrimagedecoder.cpp include/Qrimagedecoder.hpp + QML_FILES + "qml/QrCam.qml" + "qml/QrDecPop.qml" + "qml/QrTextField.qml" + RESOURCE_PREFIX + "/esterVtech.com/imports" + OUTPUT_TARGETS out_targets_var + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/Esterv/CustomControls/QrDec + IMPORT_PATH ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_LIBDIR} + ) + +add_library(${PROJECT_NAME}::QtQrDec ALIAS QtQrDec) +add_library(${PROJECT_NAME}::QtQrDecplugin ALIAS QtQrDecplugin) + + +qt6_add_shaders(QtQrDec "esterVtech.com.imports.QtQrDec.shaders" + BATCHABLE + PRECOMPILE + OPTIMIZED + OUTPUT_TARGETS out_targets_var2 + PREFIX + "/esterVtech.com/imports/Designs" + FILES + "frag/qrscanner.frag" +) +target_include_directories(QtQrDec PUBLIC $ + "$") +if(EMSCRIPTEN) + target_compile_definitions(QtQrDec PRIVATE USE_EMSCRIPTEN) +else() + target_link_libraries(QtQrDec PUBLIC Qt6::Multimedia) +endif(EMSCRIPTEN) +target_link_libraries(QtQrDec PUBLIC Qt6::Gui Qt6::Quick QrDec Qt6::Multimedia + EstervDesigns::SimpleStyle EstervDesigns::customControls + $<$,STATIC_LIBRARY>:EstervDesigns::SimpleStyleplugin> + $<$,STATIC_LIBRARY>:EstervDesigns::customControlsplugin>) + +install(TARGETS QtQrDec ${out_targets_var} ${out_targets_var2} + EXPORT ${PROJECT_NAME}-config + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT QtQrDec +) +install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Esterv/${PROJECT_NAME} + COMPONENT QtQrDec +) +install(DIRECTORY ${CMAKE_BINARY_DIR}/Esterv/CustomControls/QrDec + DESTINATION ${CMAKE_INSTALL_LIBDIR}/Esterv/CustomControls + COMPONENT QtQrDec +) + +install(TARGETS QtQrDecplugin + EXPORT ${PROJECT_NAME}-config + DESTINATION ${CMAKE_INSTALL_LIBDIR}/Esterv/CustomControls/QrDec + COMPONENT QtQrDec +) + +if(EMSCRIPTEN) + target_compile_definitions(QtQrDec PRIVATE USE_EMSCRIPTEN) +endif(EMSCRIPTEN) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + add_subdirectory(examples) +endif(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) +else(Qt6_FOUND AND TARGET QrDec) + message(STATUS "The QML Module for QRCODE decoding will not be built") endif(Qt6_FOUND AND TARGET QrDec) diff --git a/QtQrDec/Config.cmake.in b/QtQrDec/Config.cmake.in deleted file mode 100644 index 22c2283..0000000 --- a/QtQrDec/Config.cmake.in +++ /dev/null @@ -1,3 +0,0 @@ -@PACKAGE_INIT@ - -include ( "${CMAKE_CURRENT_LIST_DIR}/QtQrGenTargets.cmake" ) diff --git a/QtQrDec/Qrimagedecoder.cpp b/QtQrDec/Qrimagedecoder.cpp index b93a0df..e514591 100644 --- a/QtQrDec/Qrimagedecoder.cpp +++ b/QtQrDec/Qrimagedecoder.cpp @@ -5,71 +5,71 @@ #include - +QRImageDecoder* QRImageDecoder::m_instance=nullptr; #ifdef USE_EMSCRIPTEN #include #include -QRImageDecoder* QRImageDecoder::m_decoder=nullptr; + EMSCRIPTEN_BINDINGS(qrdecoder) { - emscripten::class_("QRImageDecoder") - .function("reload", &QRImageDecoder::reload,emscripten::allow_raw_pointers()) - .class_function("getdecoder", &QRImageDecoder::getdecoder, emscripten::allow_raw_pointers()); + emscripten::class_("QRImageDecoder") + .function("reload", &QRImageDecoder::reload,emscripten::allow_raw_pointers()) + .class_function("instance", &QRImageDecoder::instance, emscripten::allow_raw_pointers()); } EM_JS(void, js_start, (), { - if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) { - stream = navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false }).then((stream) => { - const settings = stream.getVideoTracks()[0].getSettings(); - const width = settings.width; - const height = settings.height; - - if(document.querySelector("#qrvideo")=== null) - { - let elemDiv = document.createElement('div'); - elemDiv.style.cssText = 'display:none; position:absolute;width:100%;height:100%;'; - elemDiv.innerHTML += ''; - document.body.appendChild(elemDiv); - } - const video = document.querySelector("#qrvideo"); - video.srcObject = stream; - window.localStream = stream; - - let canvas = document.querySelector("#qrcanvas"); - let ctx=canvas.getContext("2d"); - const processFrame = function () { - ctx.drawImage(video, 0, 0, canvas.width, canvas.height); - const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); - const sourceBuffer = imageData.data; - const buffer = _malloc(sourceBuffer.byteLength); - HEAPU8.set(sourceBuffer, buffer); - Module.QRImageDecoder.getdecoder().reload(buffer,video.width,video.height); - _free(buffer); - if(window.localStream.active) - { - requestAnimationFrame(processFrame); - } - else - { - ctx.clearRect(0, 0, canvas.width, canvas.height); - } - }; - processFrame(); - - - }).catch(alert); - - - } + if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) { + stream = navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false }).then((stream) => { + const settings = stream.getVideoTracks()[0].getSettings(); + const width = settings.width; + const height = settings.height; + + if(document.querySelector("#qrvideo")=== null) + { + let elemDiv = document.createElement('div'); + elemDiv.style.cssText = 'display:none; position:absolute;width:100%;height:100%;'; + elemDiv.innerHTML += ''; + document.body.appendChild(elemDiv); + } + const video = document.querySelector("#qrvideo"); + video.srcObject = stream; + window.localStream = stream; + + let canvas = document.querySelector("#qrcanvas"); + let ctx=canvas.getContext("2d"); + const processFrame = function () { + ctx.drawImage(video, 0, 0, canvas.width, canvas.height); + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const sourceBuffer = imageData.data; + const buffer = _malloc(sourceBuffer.byteLength); + HEAPU8.set(sourceBuffer, buffer); + Module.QRImageDecoder.instance().reload(buffer,video.width,video.height); + _free(buffer); + if(window.localStream.active) + { + requestAnimationFrame(processFrame); + } + else + { + ctx.clearRect(0, 0, canvas.width, canvas.height); + } + }; + processFrame(); + + + }).catch(alert); + + + } }); EM_JS(void, js_stop, (), { - if(window.localStream)window.localStream.getVideoTracks()[0].stop(); - }); + if(window.localStream)window.localStream.getVideoTracks()[0].stop(); +}); #else #if QT_CONFIG(permissions) #include @@ -77,144 +77,146 @@ EM_JS(void, js_stop, (), { void QRImageDecoder::getCamera(void) { - const QList cameras = QMediaDevices::videoInputs(); - if(cameras.size()) - { - QCameraDevice best=cameras.front(); - for (const QCameraDevice &cameraDevice : cameras) { - - if (cameraDevice.position() == QCameraDevice::BackFace) - { - best=cameraDevice; - } - } - m_camera=new QCamera(best,this); - auto bvF=best.videoFormats().at(0); - for (const QCameraFormat &format : best.videoFormats()) - { - if(abs(format.resolution().width()*1.0-format.resolution().height())setCameraFormat(bvF); - - } + const QList cameras = QMediaDevices::videoInputs(); + if(cameras.size()) + { + QCameraDevice best=cameras.front(); + for (const QCameraDevice &cameraDevice : cameras) { + + if (cameraDevice.position() == QCameraDevice::BackFace) + { + best=cameraDevice; + } + } + m_camera=new QCamera(best,this); + auto bvF=best.videoFormats().at(0); + for (const QCameraFormat &format : best.videoFormats()) + { + if(abs(format.resolution().width()*1.0-format.resolution().height())setCameraFormat(bvF); + + } } #endif - +QRImageDecoder* QRImageDecoder::instance() +{ + if (!m_instance) m_instance=new QRImageDecoder(); + return m_instance; +} QRImageDecoder::QRImageDecoder(QObject *parent):QObject(parent),m_useTorch(false),m_hasTorch(false), #ifndef USE_EMSCRIPTEN - m_camera(nullptr),captureSession(new QMediaCaptureSession(this)),videoSink(new QVideoSink(this)), + m_camera(nullptr),captureSession(new QMediaCaptureSession(this)),videoSink(new QVideoSink(this)), #endif - m_state(Ready) + m_state(Ready) { -#ifdef USE_EMSCRIPTEN - m_decoder=this; -#else - - captureSession->setVideoOutput(videoSink); - QObject::connect(videoSink,&QVideoSink::videoFrameChanged,this,[=](const QVideoFrame & Vframe) - { - - if(m_camera&&m_camera->isActive()){ - auto picture=Vframe.toImage(); - WasmImageProvider::img=picture; - setid(); - if(m_state) - { - auto var = std::thread(&QRImageDecoder::decodePicture, this,picture); - var.detach(); - } - } - }); - connect(this,&QRImageDecoder::useTorchChanged,this,[=](){ - if(m_camera->isActive()&&m_useTorch) - m_camera->setTorchMode(QCamera::TorchOn); - else - m_camera->setTorchMode(QCamera::TorchOff); - }); +#ifndef USE_EMSCRIPTEN + captureSession->setVideoOutput(videoSink); + QObject::connect(videoSink,&QVideoSink::videoFrameChanged,this,[=](const QVideoFrame & Vframe) + { + + if(m_camera&&m_camera->isActive()&&Vframe.isValid()){ + auto picture=Vframe.toImage(); + WasmImageProvider::img=picture; + setid(); + if(m_state) + { + auto var = std::thread(&QRImageDecoder::decodePicture, this,picture); + var.detach(); + } + } + }); + connect(this,&QRImageDecoder::useTorchChanged,this,[=](){ + if(m_camera->isActive()&&m_useTorch) + m_camera->setTorchMode(QCamera::TorchOn); + else + m_camera->setTorchMode(QCamera::TorchOff); + }); #endif }; void QRImageDecoder::stop(){ #ifdef USE_EMSCRIPTEN - js_stop(); + js_stop(); #else - if(m_camera)m_camera->stop(); + if(m_camera)m_camera->stop(); #endif }; void QRImageDecoder::start() { #ifdef USE_EMSCRIPTEN - js_start(); + clear(); + js_start(); #elif QT_CONFIG(permissions) - QCameraPermission cPermission; - switch (qApp->checkPermission(cPermission)) { - case Qt::PermissionStatus::Undetermined: - qApp->requestPermission(cPermission, this, - &QRImageDecoder::start); - return; - case Qt::PermissionStatus::Denied: - return; - case Qt::PermissionStatus::Granted: - if(!m_camera) - { - getCamera(); - if(m_camera) - { - captureSession->setCamera(m_camera); - QObject::connect(m_camera,&QCamera::activeChanged,[=](bool var) - { - - if(var&&m_camera->isTorchModeSupported(QCamera::TorchOn)) - { - m_hasTorch=true; - emit hasTorchChanged(); - - } - - }); - - QObject::connect(m_camera,&QCamera::errorOccurred,[](QCamera::Error error, const QString &errorString) - { - qDebug()<<"Camera Error:"<start(); - } - - return; - } + QCameraPermission cPermission; + switch (qApp->checkPermission(cPermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(cPermission, this, + &QRImageDecoder::start); + return; + case Qt::PermissionStatus::Denied: + return; + case Qt::PermissionStatus::Granted: + if(!m_camera) + { + getCamera(); + if(m_camera) + { + captureSession->setCamera(m_camera); + QObject::connect(m_camera,&QCamera::activeChanged,[=](bool var) + { + + if(var&&m_camera->isTorchModeSupported(QCamera::TorchOn)) + { + m_hasTorch=true; + emit hasTorchChanged(); + + } + + }); + + QObject::connect(m_camera,&QCamera::errorOccurred,[](QCamera::Error error, const QString &errorString) + { + qDebug()<<"Camera Error:"<start(); + } + + return; + } #endif } void QRImageDecoder::decodePicture(QImage picture) { - m_state=QRImageDecoder::Decoding; - picture.convertTo(QImage::Format_Grayscale8); - const auto str = detector.decode_grey(picture.bits(), picture.height(),picture.bytesPerLine()); - const auto qstr=QString::fromStdString(str); - if(qstr!="") - { - text=qstr; - emit text_changed(); - } - m_state=QRImageDecoder::Ready; + m_state=QRImageDecoder::Decoding; + picture.convertTo(QImage::Format_Grayscale8); + const auto str = detector.decode_grey(picture.bits(), picture.height(),picture.bytesPerLine()); + const auto qstr=QString::fromStdString(str); + if(qstr!="") + { + emit decodedQR(qstr); + } + m_state=QRImageDecoder::Ready; } QImage WasmImageProvider::img=QImage(); QImage WasmImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { - return img; + return img; } void QRImageDecoder::clear(void) { @@ -228,16 +230,16 @@ void WasmImageProvider::restart(void) } void QRImageDecoder::reload(int offset, int width, int height) { - auto imgarr = reinterpret_cast(offset); - WasmImageProvider::img=QImage(imgarr,width,height,QImage::Format_RGBA8888); + auto imgarr = reinterpret_cast(offset); + WasmImageProvider::img=QImage(imgarr,width,height,QImage::Format_RGBA8888); setid(); if(m_state)decodePicture(WasmImageProvider::img); } void QRImageDecoder::setid() { - static quint8 index=0; - source="qrimage"+QString::number(index); - emit source_changed(); - index++; + static quint8 index=0; + m_source="qrimage"+QString::number(index); + emit sourceChanged(); + index++; } diff --git a/QtQrDec/README.md b/QtQrDec/README.md index bb4ebb3..16dfb32 100644 --- a/QtQrDec/README.md +++ b/QtQrDec/README.md @@ -1,63 +1,63 @@ # QtQrDec -This repo produce a library that can detect and decode QRCODEs. +This repo produce a QML Module with custom types that can detect and decode QRCODEs. + +The types should be style independent, but the colors used relies on the [EstervDesigns](https://github.com/EddyTheCo/MyDesigns) +Simple style. +If you want to change the colors in your top qml file one can do +``` +import Esterv.Styles.Simple +... + +Component.onCompleted: +{ +Style.frontColor1= (Style.theme)?LightThemeColor:DarkThemeColor//Like control.palette.text + +Style.frontColor2= ... +Style.frontColor3= ... + +Style.backColor1= ... +Style.backColor2= ... +Style.backColor3= ... +} + +``` The detection and decoding is performed by [OpenCV](https://opencv.org/) libraries. -In case OpenCV is not found on your system CMake will download precompiled libraries from [my action releases](https://github.com/EddyTheCo/install-OpenCV-action). +In case OpenCV is not found on your system CMake will download pre compiled libraries from [my action releases](https://github.com/EddyTheCo/install-OpenCV-action). The library use [QtMultimedia](https://doc.qt.io/qt-6/qtmultimedia-index.html) if not compiling for wasm. If compiling for wasm the library creates a custom ImageProvider that communicates with the browser. You can play with the decoder on [this page](https://eddytheco.github.io/qmlonline/?example_url=qt_qr_dec) -An example on how to add the decoder to your project can be found on [this repository](https://github.com/EddyTheCo/qmlonline) (Only the parts enclosed in the USE_QtQr macros). -In general CMake produce the target 'QtQrDec' so one can link to this library like +## Adding the module to your CMake project ``` -target_link_libraries( QtQrDec) +include(FetchContent) +FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 COMPONENTS QtQrDec CONFIG +) +FetchContent_MakeAvailable(qrCode) + +target_link_libraries( qrCode::QtQrDec) ``` -## Using the decoder on QML aplications will be as simple as -``` - QrTextArea - { - id:popup_ - width:300 - height:425 - anchors.centerIn: Overlay.overlay - - description: "Get data from QRCODE" - } -``` +## Examples -For this to work one has to add the custom ImageProvider to the QML engine like in the following main.cpp -``` -#include -#include -#include "Qrimageprovider.hpp" +The [examples](examples) folder shows the use of the different custom types provided by the QML module. -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - - QQmlApplicationEngine engine; -#ifdef USE_EMSCRIPTEN - engine.addImageProvider(QLatin1String("wasm"), new WasmImageProvider()); -#endif - const QUrl url(u"qrc:/app/main.qml"_qs); - QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, - &app, [url](QObject *obj, const QUrl &objUrl) { - if (!obj && url == objUrl) - QCoreApplication::exit(-1); - }, Qt::QueuedConnection); - engine.load(url); - - return app.exec(); -} -``` +## Contributing +We appreciate any contribution! +You can open an issue or request a feature also. +You can open a PR to the `develop` branch and the CI/CD will take care of the rest. +Make sure to acknowledge your work, ideas when contributing. diff --git a/QtQrDec/examples/CMakeLists.txt b/QtQrDec/examples/CMakeLists.txt new file mode 100644 index 0000000..576e240 --- /dev/null +++ b/QtQrDec/examples/CMakeLists.txt @@ -0,0 +1,68 @@ +if(BUILD_EXAMPLES) + if(EMSCRIPTEN OR ANDROID) + find_package(Qt6 REQUIRED COMPONENTS QuickControls2) + find_package(EstervDesigns 0.4 REQUIRED COMPONENTS FlatControl CONFIG ) + endif(EMSCRIPTEN OR ANDROID) + + foreach(example "qrcam" "qrtext" + ) + qt_add_executable(${example} ${example}.cpp ) + + qt6_add_qml_module(${example} + URI E${example} + VERSION 1.0 + QML_FILES + "qml/${example}.qml" + RESOURCE_PREFIX + "/esterVtech.com/imports" + IMPORT_PATH ${CMAKE_BINARY_DIR} + ) + if(NOT EMSCRIPTEN) + target_link_libraries(${example} PRIVATE Qt6::Multimedia) + endif(NOT EMSCRIPTEN) + target_link_libraries(${example} PRIVATE Qt::Gui Qt::Qml Qt::Quick $ QtQrDec + $<$,STATIC_LIBRARY>:QtQrDecplugin> + ) + + set_target_properties(${example} PROPERTIES + WIN32_EXECUTABLE ON + MACOSX_BUNDLE ON + ) + install(TARGETS ${example} + BUNDLE DESTINATION . + DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + if(QTDEPLOY) + qt_generate_deploy_qml_app_script( + TARGET ${example} + OUTPUT_SCRIPT deploy_script + ) + install(SCRIPT ${deploy_script}) + endif(QTDEPLOY) + if(ANDROID) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_MIN_SDK_VERSION 30) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_TARGET_SDK_VERSION 34) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_SDK_BUILD_TOOLS_REVISION 34.0.0) + + FetchContent_Declare( + android_openssl + DOWNLOAD_EXTRACT_TIMESTAMP true + URL https://github.com/KDAB/android_openssl/archive/refs/heads/master.zip + ) + FetchContent_GetProperties(android_openssl) + if(NOT android_openssl_POPULATED) + FetchContent_Populate(android_openssl) + include(${android_openssl_SOURCE_DIR}/android_openssl.cmake) + add_android_openssl_libraries(${example}) + endif(NOT android_openssl_POPULATED) + + endif(ANDROID) + if(EMSCRIPTEN OR ANDROID) + target_link_libraries(${example} PRIVATE EstervDesigns::FlatControl Qt6::QuickControls2 + $<$,STATIC_LIBRARY>:EstervDesigns::FlatControlplugin> + ) + target_compile_definitions(${example} PRIVATE FORCE_STYLE="Esterv.Controls.Flat") + endif(EMSCRIPTEN OR ANDROID) + endforeach() +endif(BUILD_EXAMPLES) diff --git a/QtQrDec/examples/qml/qrcam.qml b/QtQrDec/examples/qml/qrcam.qml new file mode 100644 index 0000000..387667c --- /dev/null +++ b/QtQrDec/examples/qml/qrcam.qml @@ -0,0 +1,72 @@ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.Styles.Simple +import Esterv.CustomControls.QrDec +import Esterv.CustomControls +ApplicationWindow { + visible: true + id:window + + background:Rectangle + { + color:Style.backColor1 + } + ColumnLayout + { + anchors.fill: parent + RowLayout + { + id:rowlayout + Layout.fillHeight: true + Layout.fillWidth: true + Layout.minimumHeight: 70 + Layout.minimumWidth: 300 + ThemeSwitch + { + id:themeswitch + } + Label + { + id:label + Layout.fillHeight: true + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignBottom + text: "" + elide:Text.ElideRight + color:Style.frontColor2 + } + + Switch + { + id:onoff + + onCheckedChanged: + { + (onoff.checked)?QRImageDecoder.start():QRImageDecoder.stop(); + } + } + } + + QrCam + { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.margins: 20 + } + Connections { + target: QRImageDecoder + function onDecodedQR(data) { + label.text=data; + } + } + } + + + + + + +} diff --git a/QtQrDec/examples/qml/qrtext.qml b/QtQrDec/examples/qml/qrtext.qml new file mode 100644 index 0000000..268ba0a --- /dev/null +++ b/QtQrDec/examples/qml/qrtext.qml @@ -0,0 +1,37 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.Styles.Simple +import Esterv.CustomControls.QrDec +import Esterv.CustomControls + +ApplicationWindow { + visible: true + id:window + + background:Rectangle + { + color:Style.backColor1 + } + ThemeSwitch + { + id:themeswitch + width:45 + height:width + } + QrTextField + { + anchors.top:themeswitch.bottom + anchors.horizontalCenter:parent.horizontalCenter + width:300 + height:60 + popWidth:Math.max(parent.width*0.5,300) + popHeight:Math.max(parent.height*0.5,500) + } + + + + + + +} diff --git a/QtQrDec/examples/qrcam.cpp b/QtQrDec/examples/qrcam.cpp new file mode 100644 index 0000000..505e8cf --- /dev/null +++ b/QtQrDec/examples/qrcam.cpp @@ -0,0 +1,24 @@ +#include +#include +#include "Qrimagedecoder.hpp" + +#if defined(FORCE_STYLE) +#include +#endif +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + +#if defined(FORCE_STYLE) + QQuickStyle::setStyle(FORCE_STYLE); +#endif + QQmlApplicationEngine engine; + engine.addImageProvider(QLatin1String("wasm"), new WasmImageProvider()); + engine.addImportPath("qrc:/esterVtech.com/imports"); + const QUrl url=QUrl("qrc:/esterVtech.com/imports/Eqrcam/qml/qrcam.qml"); + + engine.load(url); + + return app.exec(); +} + diff --git a/QtQrDec/examples/qrtext.cpp b/QtQrDec/examples/qrtext.cpp new file mode 100644 index 0000000..08c613b --- /dev/null +++ b/QtQrDec/examples/qrtext.cpp @@ -0,0 +1,24 @@ +#include +#include +#include "Qrimagedecoder.hpp" + +#if defined(FORCE_STYLE) +#include +#endif +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + +#if defined(FORCE_STYLE) + QQuickStyle::setStyle(FORCE_STYLE); +#endif + QQmlApplicationEngine engine; + engine.addImageProvider(QLatin1String("wasm"), new WasmImageProvider()); + engine.addImportPath("qrc:/esterVtech.com/imports"); + const QUrl url=QUrl("qrc:/esterVtech.com/imports/Eqrtext/qml/qrtext.qml"); + + engine.load(url); + + return app.exec(); +} + diff --git a/QtQrDec/frag/qrscanner.frag b/QtQrDec/frag/qrscanner.frag new file mode 100644 index 0000000..be09eea --- /dev/null +++ b/QtQrDec/frag/qrscanner.frag @@ -0,0 +1,80 @@ +#version 440 +#define PI 3.14159265 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + vec2 pixelStep; + vec4 fcolor; +}; +layout(binding = 1) uniform sampler2D src; + +float sdOrientedBox( in vec2 p, in vec2 a, in vec2 b, float th ) +{ + float l = length(b-a); + vec2 d = (b-a)/l; + vec2 q = (p-(a+b)*0.5); + q = mat2(d.x,-d.y,d.y,d.x)*q; + q = abs(q)-vec2(l,th)*0.5; + return length(max(q,0.0)) + min(max(q.x,q.y),0.0); +} + +float frame(in vec2 uv, in float width ) +{ + float frameH=1.0-smoothstep(0.0,0.0,sdOrientedBox( uv, vec2(1.5,1.0)*width, + vec2(0.3,0.0+width), width)); + float frameV=1.0-smoothstep(0.0,0.0,sdOrientedBox( uv, vec2(1.0,0.5)*width, + vec2(0.0+width,0.3), width)); + + return clamp(frameH+frameV,0.0,1.0); + +} + + +void main( void) +{ + vec2 uv=qt_TexCoord0; + + float width=0.1; + + vec2 uv4=abs(fract(uv+0.5)-0.5); + + float d=frame(uv4,width); + + float b=0.008; + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(2.5,6.5)*width, + vec2(4.5,6.5)*width, 2.0*width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(2.5,2.5)*width, + vec2(3.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(3.5,3.5)*width, + vec2(4.5,3.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(4.5,2.5)*width, + vec2(5.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(5.5,3.5)*width, + vec2(6.5,3.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,2.5)*width, + vec2(7.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,4.5)*width, + vec2(7.5,4.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(5.5,5.5)*width, + vec2(6.5,5.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,6.5)*width, + vec2(7.5,6.5)*width, width)); + + vec4 bcolor=texture(src, uv).rgba; + vec4 color=mix(bcolor,fcolor , d); + + fragColor = color; + +} diff --git a/QtQrDec/include/Qrimagedecoder.hpp b/QtQrDec/include/Qrimagedecoder.hpp index 2c614ab..76c2795 100644 --- a/QtQrDec/include/Qrimagedecoder.hpp +++ b/QtQrDec/include/Qrimagedecoder.hpp @@ -4,6 +4,7 @@ #include #include #include + #ifndef USE_EMSCRIPTEN #include #include @@ -12,20 +13,26 @@ #include #include #endif + #include class QRImageDecoder : public QObject { Q_OBJECT - Q_PROPERTY(QString text READ get_text NOTIFY text_changed) - Q_PROPERTY(QString source READ get_source NOTIFY source_changed) + Q_PROPERTY(QString source READ get_source NOTIFY sourceChanged) Q_PROPERTY(bool useTorch MEMBER m_useTorch NOTIFY useTorchChanged) Q_PROPERTY(bool hasTorch MEMBER m_hasTorch NOTIFY hasTorchChanged) QML_ELEMENT QML_SINGLETON -public: + QRImageDecoder(QObject *parent = nullptr); +public: + static QRImageDecoder* instance(); + static QRImageDecoder *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) + { + return instance(); + } enum State { Decoding = 0, Ready @@ -33,23 +40,18 @@ class QRImageDecoder : public QObject Q_INVOKABLE void start(); Q_INVOKABLE void stop(); Q_INVOKABLE void clear(); - QString get_text(void)const{return text;} - QString get_source(void)const{return source;} + QString get_source(void)const{return m_source;} + -#ifdef USE_EMSCRIPTEN - static QRImageDecoder* getdecoder(){return m_decoder;}; -#endif void reload(int offset, int width, int height); signals: - void text_changed(); - void source_changed(); + void decodedQR(QString); + void sourceChanged(); void hasTorchChanged(); void useTorchChanged(); private: State m_state; -#ifdef USE_EMSCRIPTEN - static QRImageDecoder* m_decoder; -#else +#ifndef USE_EMSCRIPTEN QCamera* m_camera; QMediaCaptureSession* captureSession; QVideoSink* videoSink; @@ -57,9 +59,10 @@ class QRImageDecoder : public QObject #endif void setid(); void decodePicture(QImage picture); - QString text,source; + QString m_source; QRDecoder detector; bool m_useTorch,m_hasTorch; + static QRImageDecoder* m_instance; }; diff --git a/QtQrDec/qml/QrCam.qml b/QtQrDec/qml/QrCam.qml index a81c820..f12e59a 100644 --- a/QtQrDec/qml/QrCam.qml +++ b/QtQrDec/qml/QrCam.qml @@ -1,13 +1,16 @@ import QtQuick 2.0 import QtQuick.Controls import QtQuick.Layouts -import MyDesigns -import QtQrDec +import Esterv.Styles.Simple -QrQmlCamera +import Esterv.CustomControls.QrDec +Image { - id:qrscanner - property bool showClose:false; + id:control + + + cache : false + source: "image://wasm/"+QRImageDecoder.source Switch { id:useTorch @@ -19,19 +22,8 @@ QrQmlCamera { QRImageDecoder.useTorch=useTorch.checked; } + onVisibleChanged: useTorch.checked=false; + text:qsTr("Torch") } - CloseButton - { - id:cbutton - anchors.right: parent.right - anchors.top: parent.top - width: parent.width*0.15 - height:width - visible: qrscanner.showClose - onClicked: - { - qrscanner.stop(); - qrscanner.visible=false; - } - } + } diff --git a/QtQrDec/qml/QrDecPop.qml b/QtQrDec/qml/QrDecPop.qml new file mode 100644 index 0000000..ead87c8 --- /dev/null +++ b/QtQrDec/qml/QrDecPop.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 +import QtQuick.Controls +import Esterv.Styles.Simple +import Esterv.CustomControls.QrDec +import Esterv.CustomControls + +Popup +{ + id:control + property bool showClose:true; + signal gotData(string data); + onOpened: QRImageDecoder.start() + onClosed: QRImageDecoder.stop() + Connections { + target: QRImageDecoder + function onDecodedQR(data) { + if(control.enabled&&control.visible) + { + control.gotData(data); + control.visible=false; + } + } + } + QrCam + { + anchors.fill: parent + } + CloseButton + { + id:cbutton + anchors.right: parent.right + anchors.top: parent.top + visible: control.showClose + radius:width + flat:true + onClicked: + { + control.visible=false; + } + } +} diff --git a/QtQrDec/qml/QrQmlCamera.qml b/QtQrDec/qml/QrQmlCamera.qml deleted file mode 100644 index 4825128..0000000 --- a/QtQrDec/qml/QrQmlCamera.qml +++ /dev/null @@ -1,31 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls -import QtQrDec -Item -{ - id:root - signal gotdata(string data); - implicitWidth: preview.implicitWidth - implicitHeight: preview.implicitHeight - function stop() { - QRImageDecoder.stop(); - } - function start() { - QRImageDecoder.start(); - } - Connections { - target: QRImageDecoder - function onText_changed(boo) { - root.gotdata(QRImageDecoder.text) - QRImageDecoder.clear(); - } - } - Image { - id: preview - anchors.fill: root - cache : false - source: "image://wasm/"+QRImageDecoder.source - } - - -} diff --git a/QtQrDec/qml/QrTextCamPop.qml b/QtQrDec/qml/QrTextCamPop.qml deleted file mode 100644 index f373c91..0000000 --- a/QtQrDec/qml/QrTextCamPop.qml +++ /dev/null @@ -1,82 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls -import QtQuick.Layouts -import MyDesigns -import QtQrDec - -Popup -{ - id:popup_ - property alias label:tfield.label; - property alias textField:tfield.textarea; - - signal clicked(string data); - - onClosed: qrscanner.stop(); - onOpened:{ - tfield.textarea.text=""; - qrscanner.visible=false; - } - - background: Rectangle - { - id:bck - color:CustomStyle.backColor1 - border.width:1 - border.color:CustomStyle.frontColor1 - radius:Math.min(width,height)*0.05 - } - ColumnLayout - { - anchors.fill: parent - MyTextArea - { - id:tfield - Layout.alignment: Qt.AlignHCenter - Layout.margins: 20 - Layout.fillWidth: true - Layout.maximumWidth:250 - Layout.maximumHeight: 200 - focus:true - qrfill:true - onFillqr: - { - qrscanner.start(); - qrscanner.visible=true; - - } - } - QrCam - { - id:qrscanner - Layout.alignment: Qt.AlignCenter - Layout.margins: 5 - Layout.fillHeight: true - Layout.fillWidth: true - Layout.minimumWidth:100 - Layout.minimumHeight: 200 - Layout.maximumWidth: 300 - visible:false - showClose:true - onGotdata: (data)=> { - qrscanner.stop(); - qrscanner.visible=false; - tfield.textarea.text=data; - } - } - MyButton - { - id:send - Layout.alignment: Qt.AlignRight - Layout.margins: 15 - enabled: tfield.textarea.text - onClicked: - { - popup_.close(); - popup_.clicked(tfield.textarea.text); - } - text:qsTr("Ok") - } - - } -} diff --git a/QtQrDec/qml/QrTextField.qml b/QtQrDec/qml/QrTextField.qml new file mode 100644 index 0000000..71f40b6 --- /dev/null +++ b/QtQrDec/qml/QrTextField.qml @@ -0,0 +1,50 @@ +import QtQuick 2.0 +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.Styles.Simple +import Esterv.CustomControls.QrDec + +TextField +{ + id:control + property int popWidth:300 + property int popHeight:500 + rightPadding: control.height*0.9 + QrDecPop + { + id:qrpop + visible:false + closePolicy: Popup.CloseOnPressOutside + anchors.centerIn: Overlay.overlay + width:control.popWidth + height:control.popHeight + onGotData: (data) =>{control.text=data;} + + } + + Rectangle { + id:qricon + height:Math.min(parent.height,font.pixelSize) + width:height + anchors.right: parent.right + anchors.verticalCenter: control.verticalCenter + color: "transparent" + visible: !control.text&&control.enabled + ShaderEffect { + id: shader + property var src: qricon; + property color fcolor:Style.frontColor2 + property var pixelStep: Qt.vector2d(1/src.width, 1/src.height) + fragmentShader: "qrc:/esterVtech.com/imports/Designs/frag/qrscanner.frag.qsb" + anchors.fill: parent + } + MouseArea { + anchors.fill: parent + onClicked: { + qrpop.open(); + } + } + } + + +} diff --git a/QtQrGen/CMakeLists.txt b/QtQrGen/CMakeLists.txt index 3c6456f..d443009 100644 --- a/QtQrGen/CMakeLists.txt +++ b/QtQrGen/CMakeLists.txt @@ -1,71 +1,76 @@ find_package(Qt6 COMPONENTS Core Gui Qml Quick OPTIONAL_COMPONENTS Svg) -FetchContent_Declare( - MyDesigns - GIT_REPOSITORY https://github.com/EddyTheCo/MyDesigns.git - GIT_TAG v0.4.1 - FIND_PACKAGE_ARGS 0.4 CONFIG - ) -FetchContent_MakeAvailable(MyDesigns) if (Qt6_FOUND) - qt_standard_project_setup() - qt6_add_qml_module(QtQrGen - URI QtQrGen - VERSION 1.0 - SOURCES Qrimageprovider.cpp include/Qrimageprovider.hpp - QML_FILES - qml/AddressQr.qml - qml/PayQrPop.qml - qml/QrLabel.qml - RESOURCE_PREFIX - "/esterVtech.com/imports" - OUTPUT_TARGETS out_targets_var - OUTPUT_DIRECTORY - ${CMAKE_BINARY_DIR}/QtQrGen - IMPORT_PATH ${CMAKE_BINARY_DIR} - ) + qt_standard_project_setup() + qt6_add_qml_module(QtQrGen + URI Esterv.CustomControls.QrGen + VERSION ${VERSION} + SOURCES Qrimageprovider.cpp include/Qrimageprovider.hpp + QML_FILES + "qml/QrGenImage.qml" + "qml/QrGenPop.qml" + "qml/QrText.qml" + RESOURCE_PREFIX + "/esterVtech.com/imports" + OUTPUT_TARGETS out_targets_var + OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/Esterv/CustomControls/QrGen + IMPORT_PATH ${CMAKE_BINARY_DIR} ${CMAKE_INSTALL_LIBDIR} + ) +add_library(${PROJECT_NAME}::QtQrGen ALIAS QtQrGen) +add_library(${PROJECT_NAME}::QtQrGenplugin ALIAS QtQrGenplugin) +qt6_add_shaders(QtQrGen "esterVtech.com.imports.QtQrGen.shaders" + BATCHABLE + PRECOMPILE + OPTIMIZED + OUTPUT_TARGETS out_targets_var2 + PREFIX + "/esterVtech.com/imports/Designs" + FILES + "frag/qrscanner.frag" +) + +target_include_directories(QtQrGen PUBLIC $ + "$") +if(NOT TARGET Qt6::Svg) + FetchContent_Declare( + qtsvg + GIT_REPOSITORY git://code.qt.io/qt/qtsvg.git + GIT_TAG 6.5.0 + ) +FetchContent_MakeAvailable(qtsvg) +endif() - target_include_directories(QtQrGen PUBLIC $ - "$") - if(NOT TARGET Qt6::Svg) - FetchContent_Declare( - qtsvg - GIT_REPOSITORY git://code.qt.io/qt/qtsvg.git - GIT_TAG 6.5.0 - ) - FetchContent_MakeAvailable(qtsvg) - endif() +target_link_libraries(QtQrGen PUBLIC + Qt6::Quick +) +target_link_libraries(QtQrGen PRIVATE QrGen Qt6::Core Qt6::Gui Qt6::Qml Qt6::Svg + EstervDesigns::SimpleStyle EstervDesigns::customControls + $<$,STATIC_LIBRARY>:EstervDesigns::SimpleStyleplugin> + $<$,STATIC_LIBRARY>:EstervDesigns::customControlsplugin>) - target_link_libraries(QtQrGen PUBLIC - Qt6::Quick - ) - target_link_libraries(QtQrGen PRIVATE - QrGen - Qt6::Core - Qt6::Gui - Qt6::Qml - Qt6::Svg - MyDesigns - $<$,STATIC_LIBRARY>:MyDesignsplugin> - ) +install(TARGETS QtQrGen ${out_targets_var} ${out_targets_var2} + EXPORT ${PROJECT_NAME}-config + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT QtQrGen +) +install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Esterv/${PROJECT_NAME} + COMPONENT QtQrGen +) +install(DIRECTORY ${CMAKE_BINARY_DIR}/Esterv/CustomControls/QrGen + DESTINATION ${CMAKE_INSTALL_LIBDIR}/Esterv/CustomControls + COMPONENT QtQrGen +) - install(TARGETS QtQrGen QtQrGenplugin ${out_targets_var} - EXPORT qrCodeTargets - DESTINATION ${CMAKE_INSTALL_LIBDIR} - COMPONENT QtQr - ) - install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qrCode - COMPONENT QtQr - ) - install(DIRECTORY ${CMAKE_BINARY_DIR}/QtQrGen/ - DESTINATION ${CMAKE_INSTALL_LIBDIR}/QMLPlugins/QtQrGen - COMPONENT QtQr - ) +install(TARGETS QtQrGenplugin + EXPORT ${PROJECT_NAME}-config + DESTINATION ${CMAKE_INSTALL_LIBDIR}/Esterv/CustomControls/QrGen + COMPONENT QtQrGen +) +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + add_subdirectory(examples) +endif(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) endif(Qt6_FOUND) -if(BUILD_DOCS) - get_target_property(build_docs cmake_build_docs SOURCES) - include(${build_docs}) -endif() diff --git a/QtQrGen/Qrimageprovider.cpp b/QtQrGen/Qrimageprovider.cpp index 741ec9f..1664c9e 100644 --- a/QtQrGen/Qrimageprovider.cpp +++ b/QtQrGen/Qrimageprovider.cpp @@ -4,22 +4,23 @@ #include "Qrimageprovider.hpp" #include - - using namespace qrcodegen; QPixmap QRImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) { const int width = 100; - + QStringList strlist=id.split('/'); + const auto color=strlist.front(); + strlist.removeFirst(); + const auto data=strlist.join('/'); const auto max=(requestedSize.width()>requestedSize.height())?requestedSize.width():requestedSize.height(); QPixmap pixmap(max > 0 ? max : width, max> 0 ? max : width); pixmap.fill( Qt::transparent ); *size = pixmap.size(); - const QrCode qr = QrCode::encodeText(id.toStdString().c_str(), static_cast(errC)); - const auto qrSVGstr=toSvgString(qr, color.name().toStdString()); + const QrCode qr = QrCode::encodeText(data.toStdString().c_str(), static_cast(errC)); + const auto qrSVGstr=toSvgString(qr, color.toStdString()); auto qrImage=QSvgRenderer(QByteArray::fromStdString(qrSVGstr)); QPainter Painter; diff --git a/QtQrGen/README.md b/QtQrGen/README.md index b8dcbdd..3e3e8ae 100644 --- a/QtQrGen/README.md +++ b/QtQrGen/README.md @@ -1,45 +1,56 @@ # QtQrGen -This code produce a library with a custom ImageProvider of Qt. The image provider print a QRCODE from a string. -You can play with the resulting ImageProvider on [this page](https://eddytheco.github.io/qmlonline/?example_url=qt_qr_gen). - An example on how to add the ImageProvider to your project can be found on [this repository](https://github.com/EddyTheCo/qmlonline) (Only the parts enclosed in the USE_QtQr macros). +This code produce a QML module with custom types and a custom ImageProvider of Qt. +The custom types are related to the generation and showing of QRCODEs. -In general CMake produce the target 'QtQrGen' so one can link to this library like -``` -target_link_libraries( QtQrGen) + +The types should be style independent, but the colors used relies on the [EstervDesigns](https://github.com/EddyTheCo/MyDesigns) +Simple style. +If you want to change the colors in your top qml file one can do ``` +import Esterv.Styles.Simple +... +Component.onCompleted: +{ +Style.frontColor1= (Style.theme)?LightThemeColor:DarkThemeColor//Like control.palette.text -## Showing the QRCODE on QML aplications will be as simple as -``` -Image { - sourceSize.width: 300 - source: "image://qrcode/https://eddytheco.github.io/" +Style.frontColor2= ... +Style.frontColor3= ... + +Style.backColor1= ... +Style.backColor2= ... +Style.backColor3= ... } -``` -For this to work one has to add the custom ImageProvider to the QML engine like in the following main.cpp -``` -#include -#include -#include "Qrimageprovider.hpp" +``` -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - - QQmlApplicationEngine engine; - engine.addImageProvider(QLatin1String("qrCode"), new QRImageProvider("blue",1)); - const QUrl url(u"qrc:/app/main.qml"_qs); - QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, - &app, [url](QObject *obj, const QUrl &objUrl) { - if (!obj && url == objUrl) - QCoreApplication::exit(-1); - }, Qt::QueuedConnection); - engine.load(url); - - return app.exec(); -} +You can play with the ImageProvider on [this page](https://eddytheco.github.io/qmlonline/?example_url=qt_qr_gen). + + +## Adding the module to your CMake project +``` +include(FetchContent) +FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 COMPONENTS QtQrGen CONFIG +) +FetchContent_MakeAvailable(qrCode) + +target_link_libraries( qrCode::QtQrGen) ``` +## Examples + +The [examples](examples) folder shows the use of the different custom types provided by the QML module. + +## Contributing + +We appreciate any contribution! + +You can open an issue or request a feature also. +You can open a PR to the `develop` branch and the CI/CD will take care of the rest. +Make sure to acknowledge your work, ideas when contributing. diff --git a/QtQrGen/examples/CMakeLists.txt b/QtQrGen/examples/CMakeLists.txt new file mode 100644 index 0000000..009f3f6 --- /dev/null +++ b/QtQrGen/examples/CMakeLists.txt @@ -0,0 +1,64 @@ +if(BUILD_EXAMPLES) + if(EMSCRIPTEN OR ANDROID) + find_package(Qt6 REQUIRED COMPONENTS QuickControls2) + find_package(EstervDesigns 0.4 REQUIRED COMPONENTS FlatControl CONFIG ) + endif(EMSCRIPTEN OR ANDROID) + + foreach(example "image" "text" + ) + qt_add_executable(${example} ${example}.cpp ) + + qt6_add_qml_module(${example} + URI E${example} + VERSION 1.0 + QML_FILES + "qml/${example}.qml" + RESOURCE_PREFIX + "/esterVtech.com/imports" + IMPORT_PATH ${CMAKE_BINARY_DIR} + ) + target_link_libraries(${example} PRIVATE Qt::Gui Qt::Qml Qt::Quick QtQrGen + $<$,STATIC_LIBRARY>:QtQrGenplugin> + ) + + set_target_properties(${example} PROPERTIES + WIN32_EXECUTABLE ON + MACOSX_BUNDLE ON + ) + install(TARGETS ${example} + BUNDLE DESTINATION . + DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + if(QTDEPLOY) + qt_generate_deploy_qml_app_script( + TARGET ${example} + OUTPUT_SCRIPT deploy_script + ) + install(SCRIPT ${deploy_script}) + endif(QTDEPLOY) + if(ANDROID) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_MIN_SDK_VERSION 30) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_TARGET_SDK_VERSION 34) + set_property(TARGET ${example} APPEND PROPERTY QT_ANDROID_SDK_BUILD_TOOLS_REVISION 34.0.0) + + FetchContent_Declare( + android_openssl + DOWNLOAD_EXTRACT_TIMESTAMP true + URL https://github.com/KDAB/android_openssl/archive/refs/heads/master.zip + ) + FetchContent_GetProperties(android_openssl) + if(NOT android_openssl_POPULATED) + FetchContent_Populate(android_openssl) + include(${android_openssl_SOURCE_DIR}/android_openssl.cmake) + add_android_openssl_libraries(${example}) + endif(NOT android_openssl_POPULATED) + endif(ANDROID) + if(EMSCRIPTEN OR ANDROID) + target_link_libraries(${example} PRIVATE EstervDesigns::FlatControl Qt6::QuickControls2 + $<$,STATIC_LIBRARY>:EstervDesigns::FlatControlplugin> + ) + target_compile_definitions(${example} PRIVATE FORCE_STYLE="Esterv.Controls.Flat") + endif(EMSCRIPTEN OR ANDROID) + endforeach() +endif(BUILD_EXAMPLES) diff --git a/QtQrGen/examples/image.cpp b/QtQrGen/examples/image.cpp new file mode 100644 index 0000000..ac60319 --- /dev/null +++ b/QtQrGen/examples/image.cpp @@ -0,0 +1,23 @@ +#include +#include +#include "Qrimageprovider.hpp" +#if defined(FORCE_STYLE) +#include +#endif +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + +#if defined(FORCE_STYLE) + QQuickStyle::setStyle(FORCE_STYLE); +#endif + QQmlApplicationEngine engine; + engine.addImportPath("qrc:/esterVtech.com/imports"); + engine.addImageProvider(QLatin1String("qrcode"), new QRImageProvider(1)); + const QUrl url=QUrl("qrc:/esterVtech.com/imports/Eimage/qml/image.qml"); + + engine.load(url); + + return app.exec(); +} + diff --git a/QtQrGen/examples/qml/image.qml b/QtQrGen/examples/qml/image.qml new file mode 100644 index 0000000..052414d --- /dev/null +++ b/QtQrGen/examples/qml/image.qml @@ -0,0 +1,40 @@ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.Styles.Simple +import Esterv.CustomControls.QrGen +import Esterv.CustomControls + +ApplicationWindow { + visible: true + id:window + + background:Rectangle + { + color:Style.backColor1 + } + + ThemeSwitch + { + id:themeswitch + } + + QrGenImage + { + anchors.horizontalCenter:parent.horizontalCenter + anchors.top:themeswitch.bottom + width:parent.width*0.5 + height:parent.height*0.5 + textData:"https://eddytheco.github.io/" + } + + + + + + + + + +} diff --git a/QtQrGen/examples/qml/text.qml b/QtQrGen/examples/qml/text.qml new file mode 100644 index 0000000..1b5b649 --- /dev/null +++ b/QtQrGen/examples/qml/text.qml @@ -0,0 +1,40 @@ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.Styles.Simple +import Esterv.CustomControls.QrGen +import Esterv.CustomControls + +ApplicationWindow { + visible: true + id:window + + background:Rectangle + { + color:Style.backColor1 + } + + ThemeSwitch + { + id:themeswitch + } + + QrText + { + anchors.horizontalCenter:parent.horizontalCenter + anchors.top:themeswitch.bottom + text:"smr1qp9rtwlc00ksp0mvet8ugwvqu03ygzr8s3x77w3df9qw9srm3hwk2l0v9kf" + width:parent.width*0.5 + font.pixelSize: 30 + } + + + + + + + + + +} diff --git a/QtQrGen/examples/text.cpp b/QtQrGen/examples/text.cpp new file mode 100644 index 0000000..02dee2a --- /dev/null +++ b/QtQrGen/examples/text.cpp @@ -0,0 +1,23 @@ +#include +#include +#include "Qrimageprovider.hpp" +#if defined(FORCE_STYLE) +#include +#endif +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + +#if defined(FORCE_STYLE) + QQuickStyle::setStyle(FORCE_STYLE); +#endif + QQmlApplicationEngine engine; + engine.addImportPath("qrc:/esterVtech.com/imports"); + engine.addImageProvider(QLatin1String("qrcode"), new QRImageProvider(1)); + const QUrl url=QUrl("qrc:/esterVtech.com/imports/Etext/qml/text.qml"); + + engine.load(url); + + return app.exec(); +} + diff --git a/QtQrGen/frag/qrscanner.frag b/QtQrGen/frag/qrscanner.frag new file mode 100644 index 0000000..be09eea --- /dev/null +++ b/QtQrGen/frag/qrscanner.frag @@ -0,0 +1,80 @@ +#version 440 +#define PI 3.14159265 +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + vec2 pixelStep; + vec4 fcolor; +}; +layout(binding = 1) uniform sampler2D src; + +float sdOrientedBox( in vec2 p, in vec2 a, in vec2 b, float th ) +{ + float l = length(b-a); + vec2 d = (b-a)/l; + vec2 q = (p-(a+b)*0.5); + q = mat2(d.x,-d.y,d.y,d.x)*q; + q = abs(q)-vec2(l,th)*0.5; + return length(max(q,0.0)) + min(max(q.x,q.y),0.0); +} + +float frame(in vec2 uv, in float width ) +{ + float frameH=1.0-smoothstep(0.0,0.0,sdOrientedBox( uv, vec2(1.5,1.0)*width, + vec2(0.3,0.0+width), width)); + float frameV=1.0-smoothstep(0.0,0.0,sdOrientedBox( uv, vec2(1.0,0.5)*width, + vec2(0.0+width,0.3), width)); + + return clamp(frameH+frameV,0.0,1.0); + +} + + +void main( void) +{ + vec2 uv=qt_TexCoord0; + + float width=0.1; + + vec2 uv4=abs(fract(uv+0.5)-0.5); + + float d=frame(uv4,width); + + float b=0.008; + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(2.5,6.5)*width, + vec2(4.5,6.5)*width, 2.0*width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(2.5,2.5)*width, + vec2(3.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(3.5,3.5)*width, + vec2(4.5,3.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(4.5,2.5)*width, + vec2(5.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(5.5,3.5)*width, + vec2(6.5,3.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,2.5)*width, + vec2(7.5,2.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,4.5)*width, + vec2(7.5,4.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(5.5,5.5)*width, + vec2(6.5,5.5)*width, width)); + + d+=1.0-smoothstep(0.0,b,sdOrientedBox( uv, vec2(6.5,6.5)*width, + vec2(7.5,6.5)*width, width)); + + vec4 bcolor=texture(src, uv).rgba; + vec4 color=mix(bcolor,fcolor , d); + + fragColor = color; + +} diff --git a/QtQrGen/include/Qrimageprovider.hpp b/QtQrGen/include/Qrimageprovider.hpp index 42b91a2..b455aba 100644 --- a/QtQrGen/include/Qrimageprovider.hpp +++ b/QtQrGen/include/Qrimageprovider.hpp @@ -4,15 +4,14 @@ class QRImageProvider : public QQuickImageProvider { public: - QRImageProvider(QColor col="black",int erc=0) - : QQuickImageProvider(QQuickImageProvider::Pixmap),color(col),errC(erc) + QRImageProvider(int erc=0) + : QQuickImageProvider(QQuickImageProvider::Pixmap),errC(erc) { } QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override; private: - const QColor color; const int errC; }; diff --git a/QtQrGen/qml/AddressQr.qml b/QtQrGen/qml/AddressQr.qml deleted file mode 100644 index 2c541a7..0000000 --- a/QtQrGen/qml/AddressQr.qml +++ /dev/null @@ -1,47 +0,0 @@ -import QtQuick.Controls -import QtQuick -import MyDesigns -import QtQrGen - -Rectangle { - id:root - required property string address - property string url - radius: 10 - - TextClipboard - { - id:tclip - text:root.address - } - - Image { - id:img - anchors.centerIn:parent - sourceSize.width: root.width-10 - source: "image://qrcodeblack/"+root.address - MouseArea { - anchors.fill: img - hoverEnabled :true - onEntered: tooltip.visible=!tooltip.visible - onExited: tooltip.visible=!tooltip.visible - onClicked: - { - - tclip.copy(); - if(root.url) - { - Qt.openUrlExternally(root.url) - } - } - } - } - ToolTip - { - id:tooltip - visible: false - text:qsTr("Copy") - } - - -} diff --git a/QtQrGen/qml/PayQrPop.qml b/QtQrGen/qml/PayQrPop.qml deleted file mode 100644 index 3387041..0000000 --- a/QtQrGen/qml/PayQrPop.qml +++ /dev/null @@ -1,57 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls -import QtQuick.Layouts -import MyDesigns -import QtQrGen - -Popup { - id: root - required property string address; - property string url; - required property string description; - property alias qrcode:qrcode_; - - background: Rectangle - { - id:bck - color:CustomStyle.backColor1 - border.width:1 - border.color:CustomStyle.frontColor1 - radius:Math.min(width,height)*0.05 - - } - - modal: true - focus: true - - ColumnLayout - { - anchors.fill: parent - spacing:10 - MyTextArea - { - id:tex - Layout.fillWidth: true - Layout.fillHeight: true - Layout.alignment: Qt.AlignTop|Qt.AlignHCenter - Layout.minimumHeight: 100 - label.visible: false - textarea.text: root.description - textarea.readOnly: true - textarea.wrapMode: Text.Wrap - } - - - AddressQr - { - id:qrcode_ - address:root.address - url:root.url - Layout.preferredWidth: tex.width*0.75 - Layout.preferredHeight: width - Layout.alignment: Qt.AlignCenter - } - } - -} - diff --git a/QtQrGen/qml/QrGenImage.qml b/QtQrGen/qml/QrGenImage.qml new file mode 100644 index 0000000..502a275 --- /dev/null +++ b/QtQrGen/qml/QrGenImage.qml @@ -0,0 +1,22 @@ +import QtQuick.Controls +import QtQuick +import QtQml +import Esterv.Styles.Simple + +Control +{ + id:control + required property string textData + implicitWidth: 100 + implicitHeight: 100 + background: Rectangle { + radius: Math.min(width,height)*0.8*Style.roundedScale/Style.Scale.Full + color:Style.backColor3 + } + Image { + id:img + anchors.centerIn:parent + sourceSize.width: Math.min(control.width,control.height)-control.background.radius-10 + source: "image://qrcode/"+Style.frontColor1+"/"+control.textData + } +} diff --git a/QtQrGen/qml/QrGenPop.qml b/QtQrGen/qml/QrGenPop.qml new file mode 100644 index 0000000..bee696e --- /dev/null +++ b/QtQrGen/qml/QrGenPop.qml @@ -0,0 +1,74 @@ +import QtQuick 2.0 +import QtQuick.Controls +import QtQuick.Layouts +import Esterv.CustomControls +import Esterv.Styles.Simple + +Popup { + id: control + required property string textData; + property bool showClose:true; + + ColumnLayout + { + anchors.fill:parent + Item + { + Layout.fillHeight: true + Layout.fillWidth: true + Layout.minimumHeight: 50 + Layout.maximumHeight: 100 + Switch + { + id:showdata + text: qsTr("Show text") + } + CloseButton + { + id:cbutton + anchors.top: parent.top + radius:width + anchors.right: parent.right + visible: control.showClose + + flat:true + onClicked: + { + control.visible=false; + } + } + } + Item + { + Layout.minimumHeight: 100 + Layout.minimumWidth: 200 + Layout.fillWidth: true + Layout.fillHeight: true + ScrollView { + anchors.fill:parent + TextArea + { + id:tex + text: control.textData + readOnly: true + wrapMode: Text.Wrap + + } + } + visible:showdata.checked + } + QrGenImage + { + id:qrgenimage + textData:control.textData + visible:!tex.visible + Layout.fillHeight: true + Layout.fillWidth: true + } + + } + + + +} + diff --git a/QtQrGen/qml/QrLabel.qml b/QtQrGen/qml/QrLabel.qml deleted file mode 100644 index 330db9a..0000000 --- a/QtQrGen/qml/QrLabel.qml +++ /dev/null @@ -1,36 +0,0 @@ -import QtQuick.Controls -import QtQuick -import MyDesigns -import QtQrGen - - - -Text -{ - id:root - property string description:""; - required property string address; - - PayQrPop - { - id:popup_ - address:root.address - description:root.address - visible:false - closePolicy: Popup.CloseOnPressOutside - anchors.centerIn: Overlay.overlay - focus: false - modal:false - width:300 - } - - text:((root.description)?(""+ root.description +': '):'') +' '+ root.address +'' - elide:Text.ElideRight - horizontalAlignment: TextEdit.AlignLeft - fontSizeMode:Text.VerticalFit - color:CustomStyle.frontColor1 - MouseArea { - anchors.fill: parent - onClicked: popup_.visible=true; - } -} diff --git a/QtQrGen/qml/QrText.qml b/QtQrGen/qml/QrText.qml new file mode 100644 index 0000000..0349db9 --- /dev/null +++ b/QtQrGen/qml/QrText.qml @@ -0,0 +1,50 @@ +import QtQuick.Controls +import QtQuick + +import Esterv.Styles.Simple + + +Text +{ + id:control + property int popWidth:300 + property int popHeight:500 + QrGenPop + { + id:qrgenpop + textData:control.text + visible:false + closePolicy: Popup.CloseOnPressOutside + anchors.centerIn: Overlay.overlay + width:control.popWidth + height:control.popHeight + } + color:Style.frontColor1 + elide:Text.ElideRight + horizontalAlignment: TextEdit.AlignLeft + + rightPadding: control.height*0.9 + + Rectangle { + id:qricon + height:Math.min(parent.height,font.pixelSize) + width:height + x: parent.contentWidth + color: "transparent" + ShaderEffect { + id: shader + property var src: qricon; + property color fcolor:Style.frontColor2 + property var pixelStep: Qt.vector2d(1/src.width, 1/src.height) + fragmentShader: "qrc:/esterVtech.com/imports/Designs/frag/qrscanner.frag.qsb" + anchors.fill: parent + } + + } + MouseArea { + anchors.fill: parent + onClicked: { + qrgenpop.open(); + } + } +} diff --git a/README.md b/README.md index c92a1e7..d403460 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,28 @@ # qrCode This repository is intended to provide a library for working with QR codes from c++. The main purpose is to exploit modern CMake and facilitate reuse and develop. -The GUI part will be based on Qt libraries and QML. Examples of this library compiled for WebAssembly can be found on: + +The GUI part will be based on Qt libraries and QML. Examples of this library compiled for Web Assembly can be found on: - [QtQrGen](https://eddytheco.github.io/qmlonline/?example_url=qt_qr_gen) - [QtQrDec](https://eddytheco.github.io/qmlonline/?example_url=qt_qr_dec) -## Adding the libraries to your CMake project will be as easy as +## Adding the libraries to your CMake project ```CMake include(FetchContent) - FetchContent_Declare( - qrCode - GIT_REPOSITORY git@github.com:EddyTheCo/qrCode.git - GIT_TAG v0.1.2 - FIND_PACKAGE_ARGS 0.1 CONFIG - ) +FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v1.0.0 + FIND_PACKAGE_ARGS 1.0 CONFIG + ) FetchContent_MakeAvailable(qrCode) -target_link_libraries( QrGen QtQrGen QrDec QtQrDec) +target_link_libraries( qrCode::QrGen qrCode::QtQrGen qrCode::QrDec qrCode::QtQrDec) ``` For more information check - +- [QrGen](QrGen/README.md) +- [QrDec](QrDec/README.md) - [QtQrGen](QtQrGen/README.md) - [QtQrDec](QtQrDec/README.md)