diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 00000000..68128032 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,81 @@ +--- +name: BUG Report | 缺陷报告 +description: General BUG report +body: +- type: markdown + attributes: + value: | + **Thanks for taking a minute to file a bug report!** + **感谢抽出时间汇报 BUG 缺陷!** + + A valid bug report should let someone other than you be able to reproduce the same issue, so please provide as much details as possible. + 一个有效的缺陷汇报应当能够使一个你之外的人可以根据所提供的信息有效的复现问题。所以请提供尽可能详细的信息。 + + ⚠ Read before creating issue 反馈之前请注意: + Only report BUG here, please use the [Discussion board][discussion-board] for non-bug feature request, troubleshooting or general discusion. + 非 BUG 的反馈(如特性请求,疑难解答,行为建议,常规讨论)请转到 [Discussion 面板][discussion-board] + + [discussion-board]: https://github.com/linuxdeepin/developer-center/discussions/new + +- type: textarea + attributes: + label: SUMMARY | 问题概要 + description: | + describe the bug you want to report + 在这里描述你遇到的 BUG + +- type: textarea + attributes: + label: SOFTWARE/OS VERSIONS | 软件/系统版本信息 + description: | + describe the related application/package version information + 在这里描述与之相关的软件和系统版本信息 + placeholder: | + Example: + Distribution: deepin v20.9 + Package: deepin-example 5.1.4-1 + validations: + required: true + +- type: textarea + attributes: + label: PRE-REQUIREMENT | 预置条件 + description: | + describe the setup that is required to reproduce the bug before attempt to reproduce + 在这里描述用于复现 BUG 的预置条件 + +- type: textarea + attributes: + label: STEPS TO REPRODUCE | 复现步骤 + description: | + describe the steps to reproduce the specific bug + 在这里描述复现 BUG 的操作步骤 + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: true + +- type: textarea + attributes: + label: OBSERVED RESULT | 观察到的结果 + description: | + describe the observed result + 在这里描述观察到的结果 + +- type: textarea + attributes: + label: EXPECTED RESULT | 期望的结果 + description: | + describe the expected result + 在这里描述你所期望的结果 + +- type: textarea + attributes: + label: ADDITIONAL INFORMATION | 额外补充 + description: | + any additional information you may want to provide so we can offer better help + 有什么额外需要补充的信息的话,可以写到这里 + +... diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..74688d9b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Feature Request | 特性请求 + url: https://github.com/linuxdeepin/developer-center/discussions/new?category=features-request-ideas-%E7%89%B9%E6%80%A7%E8%AF%B7%E6%B1%82-%E5%A4%B4%E8%84%91%E9%A3%8E%E6%9A%B4 + about: Please create feature requests to the discussion board in our developer-center repo. + - name: Troubleshooting | 故障排查 + url: https://github.com/linuxdeepin/developer-center/discussions/categories/troubleshooting-%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5 + about: Something does not work but not sure if it is a bug? Report here. + - name: General Discussion & Questions | 常规讨论与问答 + url: https://github.com/linuxdeepin/developer-center/discussions/categories/q-a-%E9%97%AE%E7%AD%94%E6%9D%BF%E5%9D%97 + about: Please use the discussion board in our developer-center repo. diff --git a/.github/ISSUE_TEMPLATE/document-report.yml b/.github/ISSUE_TEMPLATE/document-report.yml new file mode 100644 index 00000000..3115a168 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/document-report.yml @@ -0,0 +1,10 @@ +--- +name: Document Problem Report | 文档问题报告 +description: Document Problem Report +body: +- type: textarea + attributes: + label: SUMMARY | 问题概要 + description: | + describe the problem you want to report + 在这里描述你遇到的文档方面的问题 diff --git a/.github/ISSUE_TEMPLATE/unit-test-report.yml b/.github/ISSUE_TEMPLATE/unit-test-report.yml new file mode 100644 index 00000000..4e144f0b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/unit-test-report.yml @@ -0,0 +1,24 @@ +--- +name: Unit Test Report | 单元测试报告 +description: Unit Test Report +body: +- type: textarea + attributes: + label: SUMMARY | 问题概要 + description: | + describe the problem you want to report + 在这里描述你遇到的单元测试问题 + +- type: textarea + attributes: + label: PATH | 单元测试文件路径 + description: | + specify the unit test file path + 遇到问题的单元测试文件路径 + +- type: textarea + attributes: + label: INTERFACE | 测试接口 + description: | + specify the test interface + 单元测试测试的接口 diff --git a/.github/workflows/backup-to-gitlab.yml b/.github/workflows/backup-to-gitlab.yml new file mode 100644 index 00000000..9863040f --- /dev/null +++ b/.github/workflows/backup-to-gitlab.yml @@ -0,0 +1,15 @@ +name: backup to gitlab +on: [push] + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + backup-to-gitlabwh: + uses: linuxdeepin/.github/.github/workflows/backup-to-gitlabwh.yml@master + secrets: inherit + + backup-to-gitee: + uses: linuxdeepin/.github/.github/workflows/backup-to-gitee.yml@master + secrets: inherit diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 25e89164..00000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: CI Build - -on: - push: - branches: - - master - - pull_request: - branches: - - master - -jobs: - archlinux: - name: Archlinux Build Check - runs-on: ubuntu-latest - steps: - - name: Checkout branch - uses: actions/checkout@v2 - - name: build - uses: justforlxz/deepin-git-action@v1 - with: - repo: deepin-session-shell diff --git a/.github/workflows/call-auto-tag.yml b/.github/workflows/call-auto-tag.yml new file mode 100644 index 00000000..5018e5be --- /dev/null +++ b/.github/workflows/call-auto-tag.yml @@ -0,0 +1,16 @@ +name: auto tag + +on: + pull_request_target: + types: [opened, synchronize, closed] + paths: + - "debian/changelog" + +concurrency: + group: ${{ github.workflow }}-pull/${{ github.event.number }} + cancel-in-progress: true + +jobs: + auto_tag: + uses: linuxdeepin/.github/.github/workflows/auto-tag.yml@master + secrets: inherit diff --git a/.github/workflows/call-build-distribution.yml b/.github/workflows/call-build-distribution.yml new file mode 100644 index 00000000..a509d5f8 --- /dev/null +++ b/.github/workflows/call-build-distribution.yml @@ -0,0 +1,13 @@ +name: Call build-distribution +on: + push: + paths-ignore: + - ".github/workflows/**" + pull_request_target: + paths-ignore: + - ".github/workflows/**" + +jobs: + check_job: + uses: linuxdeepin/.github/.github/workflows/build-distribution.yml@master + secrets: inherit diff --git a/.github/workflows/call-chatOps.yml b/.github/workflows/call-chatOps.yml new file mode 100644 index 00000000..18c76bc3 --- /dev/null +++ b/.github/workflows/call-chatOps.yml @@ -0,0 +1,9 @@ +name: chatOps +on: + issue_comment: + types: [created] + +jobs: + chatopt: + uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master + secrets: inherit diff --git a/.github/workflows/call-clacheck.yml b/.github/workflows/call-clacheck.yml new file mode 100644 index 00000000..fe16a073 --- /dev/null +++ b/.github/workflows/call-clacheck.yml @@ -0,0 +1,15 @@ +name: Call CLA check +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, closed, synchronize] + +concurrency: + group: ${{ github.workflow }}-pull/${{ github.event.number }} + cancel-in-progress: true + +jobs: + clacheck: + uses: linuxdeepin/.github/.github/workflows/cla-check.yml@master + secrets: inherit diff --git a/.github/workflows/call-commitlint.yml b/.github/workflows/call-commitlint.yml new file mode 100644 index 00000000..69f5b2dc --- /dev/null +++ b/.github/workflows/call-commitlint.yml @@ -0,0 +1,11 @@ +name: Call commitlint +on: + pull_request_target: + +concurrency: + group: ${{ github.workflow }}-pull/${{ github.event.number }} + cancel-in-progress: true + +jobs: + check_job: + uses: linuxdeepin/.github/.github/workflows/commitlint.yml@master diff --git a/.github/workflows/call-license-check.yml b/.github/workflows/call-license-check.yml new file mode 100644 index 00000000..347d5560 --- /dev/null +++ b/.github/workflows/call-license-check.yml @@ -0,0 +1,16 @@ +name: Call License and README Check +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + pull-requests: write + contents: read + +concurrency: + group: ${{ github.workflow }}-pull/${{ github.event.number }} + cancel-in-progress: true + +jobs: + license-check: + uses: linuxdeepin/.github/.github/workflows/license-check.yml@master diff --git a/.github/workflows/call-update-changelog.yml b/.github/workflows/call-update-changelog.yml new file mode 100644 index 00000000..b76b9b3f --- /dev/null +++ b/.github/workflows/call-update-changelog.yml @@ -0,0 +1,53 @@ +name: Call update changelog + +on: + workflow_dispatch: + inputs: + version: + description: "Target version; leave empty to auto bump" + required: false + type: string + name: + description: "Maintainer name used in debian/changelog" + required: true + type: string + email: + description: "Maintainer email used in debian/changelog" + required: true + type: string + base_branch: + description: "Base branch to read and target" + required: false + default: master + type: string + distribution: + description: "Changelog distribution" + required: false + default: unstable + type: string + create_pr: + description: "Create a pull request after generating changelog" + required: false + default: true + type: boolean + +jobs: + update_changelog: + uses: linuxdeepin/.github/.github/workflows/update-changelog.yml@master + with: + version: ${{ inputs.version }} + name: ${{ inputs.name }} + email: ${{ inputs.email }} + base_branch: ${{ inputs.base_branch }} + distribution: ${{ inputs.distribution }} + create_pr: ${{ inputs.create_pr }} + secrets: inherit + + show_result: + runs-on: ubuntu-latest + needs: update_changelog + steps: + - name: Show update changelog result + run: | + echo "Version: ${{ needs.update_changelog.outputs.version }}" + echo "Pull Request URL: ${{ needs.update_changelog.outputs.pr_url }}" diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml new file mode 100644 index 00000000..e808a89b --- /dev/null +++ b/.github/workflows/cppcheck.yml @@ -0,0 +1,26 @@ +name: cppcheck +on: + pull_request_target: + paths-ignore: + - ".github/workflows/**" + +concurrency: + group: ${{ github.workflow }}-pull/${{ github.event.number }} + cancel-in-progress: true + +jobs: + cppchceck: + name: cppcheck + runs-on: ubuntu-latest + steps: + - run: export + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false + - uses: linuxdeepin/action-cppcheck@main + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + repository: ${{ github.repository }} + pull_request_id: ${{ github.event.pull_request.number }} + allow_approve: false diff --git a/.gitignore b/.gitignore index 37ff2bea..63b1fefc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ build*/ *.core *.autosave *.user* +obj-x86_64-linux-gnu/* # qm file is auto generate from .ts file *.qm @@ -28,3 +29,7 @@ build*/ *.vscode tests/report/* .transifexrc +.cache/ +.cursor/ +# for snipe +src/global_util/dbus/* diff --git a/.obs/workflows.yml b/.obs/workflows.yml new file mode 100644 index 00000000..ada468a8 --- /dev/null +++ b/.obs/workflows.yml @@ -0,0 +1,50 @@ +test_build: + steps: + - link_package: + source_project: deepin:Develop:dde + source_package: %{SCM_REPOSITORY_NAME} + target_project: deepin:CI + + - configure_repositories: + project: deepin:CI + repositories: + - name: deepin_develop + paths: + - target_project: deepin:CI + target_repository: deepin_develop + architectures: + - x86_64 + - aarch64 + + - name: debian + paths: + - target_project: deepin:CI + target_repository: debian_sid + architectures: + - x86_64 + + - name: archlinux + paths: + - target_project: deepin:CI + target_repository: archlinux + architectures: + - x86_64 + + filters: + event: pull_request + +tag_build: + steps: + - trigger_services: + project: deepin:Unstable:dde + package: %{SCM_REPOSITORY_NAME} + filters: + event: tag_push + +commit_build: + steps: + - trigger_services: + project: deepin:Develop:dde + package: %{SCM_REPOSITORY_NAME} + filters: + event: push diff --git a/.tx/config b/.tx/config index 711ab4e5..745c953e 100644 --- a/.tx/config +++ b/.tx/config @@ -1,10 +1,15 @@ [main] host = https://www.transifex.com -minimum_perc = 80 -mode = developer -[deepin-desktop-environment.dde-session-shell] +[o:linuxdeepin:p:deepin-desktop-environment:r:7b6846181f3a648d8293f3e4693d31cc] file_filter = translations/dde-session-shell_.ts source_file = translations/dde-session-shell_en.ts source_lang = en type = QT + +[o:linuxdeepin:p:deepin-desktop-environment:r:ba0d8d02ba70d7f954ec191e4d0303be] +file_filter = plugins/login-gesture/translations/login-gesture_.ts +source_file = plugins/login-gesture/translations/login-gesture_en.ts +source_lang = en +type = QT + diff --git a/.tx/deepin.conf b/.tx/deepin.conf new file mode 100644 index 00000000..45cd054c --- /dev/null +++ b/.tx/deepin.conf @@ -0,0 +1,2 @@ +[transifex] +branch = m20 \ No newline at end of file diff --git a/.tx/transifex.yaml b/.tx/transifex.yaml new file mode 100644 index 00000000..1061912c --- /dev/null +++ b/.tx/transifex.yaml @@ -0,0 +1,13 @@ +filters: +- filter_type: file + source_file: translations/dde-session-shell_en.ts + file_format: QT + source_language: en + translation_files_expression: translations/dde-session-shell_.ts +- filter_type: file + source_file: plugins/login-gesture/translations/login-gesture_en.ts + file_format: QT + source_language: en + translation_files_expression: plugins/login-gesture/translations/login-gesture_.ts +settings: + pr_branch_name: transifex_update_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b81b1c6..c35a899b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,18 @@ -cmake_minimum_required(VERSION 3.13.4) +cmake_minimum_required(VERSION 3.16) project(dde-session-shell C CXX) -set(CMAKE_CXX_STANDARD 14) +include(GNUInstallDirs) +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX /usr) +endif () + +set(CMAKE_CXX_STANDARD 17) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -pthread -Wl,--as-need -fPIE -Wl,-E") -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -ggdb") -SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall") set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) -# 增加安全编译参数 -set(SECURITY_COMPILE, "-fstack-protector-all -fPIC") -set(CMAKE_CXX_FLAGS, "${CMAKE_CXX_FLAGS} ${SECURITY_COMPILE}") -set(CMAKE_C_FLAGS, "${CMAKE_C_FLAGS} ${SECURITY_COMPILE}") - # coverage option # cmake -DENABLE_COVERAGE=ON .. OPTION (ENABLE_COVERAGE "Use gcov" OFF) @@ -29,90 +27,207 @@ if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ftree-vectorize -march=loongson3a -mhard-float -mno-micromips -mno-mips16 -flax-vector-conversions -mloongson-ext2 -mloongson-mmi") endif() -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now -z noexecstack -pie") - -if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Debug")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast") +# DDE_SESSION_SHELL_SNIPE defined in snipe repo +if (NOT DDE_SESSION_SHELL_SNIPE) + find_package(Qt6 COMPONENTS Core QUIET) +endif () - # generate qm - execute_process(COMMAND bash "translate_generation.sh" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +if (DDE_SESSION_SHELL_SNIPE OR Qt6_FOUND) + add_definitions(-DENABLE_DSS_SNIPE) + set(DISABLE_DSS_SNIPE FALSE) + set(QT_VERSION_MAJOR 6) + set(DTK_VERSION_MAJOR 6) +else () + # for v20 + set(DISABLE_DSS_SNIPE TRUE) + set(QT_VERSION_MAJOR 5) + set(DTK_VERSION_MAJOR "") endif () +message(STATUS "Using Qt${QT_VERSION_MAJOR} (Dtk${DTK_VERSION_MAJOR})") + # Find the library find_package(PAM REQUIRED) find_package(PkgConfig REQUIRED) -find_package(DtkWidget REQUIRED) -find_package(DtkCMake REQUIRED) -find_package(DtkCore REQUIRED) -find_package(Qt5 COMPONENTS - Core - Widgets - Concurrent - X11Extras - DBus - Xml - Svg - Network -REQUIRED) +find_package(Threads REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets DBus Svg Network) +find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED COMPONENTS Widget Core) + +if (DISABLE_DSS_SNIPE) + find_package(KF5Wayland REQUIRED) + find_package(Qt5 COMPONENTS X11Extras REQUIRED) + + pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) + pkg_check_modules(QGSettings REQUIRED gsettings-qt) + pkg_check_modules(Greeter REQUIRED liblightdm-qt5-3) +else () + find_package(Qt6 COMPONENTS LinguistTools REQUIRED) + find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS REQUIRED Tools) + pkg_check_modules(Greeter REQUIRED liblightdm-qt6-3) +endif () pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xi xcursor xfixes xrandr xext xtst) -pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) -pkg_check_modules(QGSettings REQUIRED gsettings-qt) -pkg_check_modules(Greeter REQUIRED liblightdm-qt5-3) +pkg_check_modules(SSL REQUIRED IMPORTED_TARGET libcrypto libssl openssl) + +if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Debug")) + if (DISABLE_DSS_SNIPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Ofast") + # generate qm + execute_process(COMMAND bash "translate_generation.sh" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + else () + file(GLOB TS_FILES "translations/*.ts") + qt_add_translation(QM_FILES ${TS_FILES}) + add_custom_target(dde-session-shell_language ALL DEPENDS ${QM_FILES}) + endif () +endif () set(Qt_LIBS - Qt5::Core - Qt5::Gui - Qt5::DBus - Qt5::Widgets - Qt5::X11Extras - Qt5::Xml - Qt5::Svg + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Gui + Qt${QT_VERSION_MAJOR}::DBus + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Svg +) + +if (DISABLE_DSS_SNIPE) + list(APPEND Qt_LIBS Qt5::X11Extras) +endif() + +if (DISABLE_DSS_SNIPE) + try_compile(USE_DEEPIN_WAYLAND + ${CMAKE_CURRENT_BINARY_DIR}/try_compile + SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/tests/wayland_test.cc + LINK_LIBRARIES + ${Qt_LIBS} + ${Qt5Widgets_LIBRARIES} + KF5::WaylandClient + ) + + message(STATUS "USE_DEEPIN_WAYLAND ${USE_DEEPIN_WAYLAND}") + + if(USE_DEEPIN_WAYLAND) + add_definitions(-DUSE_DEEPIN_WAYLAND) + endif() +endif () + +try_compile(USE_GM + ${CMAKE_CURRENT_BINARY_DIR}/try_compile + SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_gm.cc + LINK_LIBRARIES + PkgConfig::SSL + OUTPUT_VARIABLE + GM_MESSAGE ) +message(STATUS "check GM: ${USE_GM}") + +if (${CMAKE_BUILD_TYPE} MATCHES "Debug") + message(${GM_MESSAGE}) +endif() + +if(USE_GM) + # 优先使用国密 + add_definitions(-DPREFER_USING_GM) +endif() + function(generation_dbus_interface xml class_name class_file option) - execute_process(COMMAND qdbusxml2cpp ${option} -p ${class_file} -c ${class_name} ${xml} + execute_process(COMMAND /usr/lib/qt${QT_VERSION_MAJOR}/bin/qdbusxml2cpp ${option} -p ${class_file} -c ${class_name} ${xml} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endfunction(generation_dbus_interface) +set (SWITCH_OS_XML "${CMAKE_SOURCE_DIR}/xml/com.huawei.switchos.xml") +if (DISABLE_DSS_SNIPE) + set(AUTHENTICATE_XML "${CMAKE_SOURCE_DIR}/xml/com.deepin.daemon.Authenticate.xml") +else () + set(AUTHENTICATE_XML "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Authenticate1.xml") +endif () + generation_dbus_interface( - ${CMAKE_SOURCE_DIR}/xml/com.deepin.daemon.Authenticate.xml + ${AUTHENTICATE_XML} AuthenticateInterface ${CMAKE_CURRENT_BINARY_DIR}/authenticate_interface -N ) -set(authority_DBUS_SCRS +set(AUTH_DBUS_SCRS ${CMAKE_CURRENT_BINARY_DIR}/authenticate_interface.h ${CMAKE_CURRENT_BINARY_DIR}/authenticate_interface.cpp ) generation_dbus_interface( - ${CMAKE_SOURCE_DIR}/xml/com.huawei.switchos.xml + ${SWITCH_OS_XML} HuaWeiSwitchOSInterface ${CMAKE_CURRENT_BINARY_DIR}/switchos_interface -N ) -set(haweiswitchos_DBUS_SCRS +set(SWITCHOS_DBUS_SCRS ${CMAKE_CURRENT_BINARY_DIR}/switchos_interface.h ${CMAKE_CURRENT_BINARY_DIR}/switchos_interface.cpp ) +# for snipe +if (NOT DISABLE_DSS_SNIPE) + set(XML2CPP_DIR ${PROJECT_SOURCE_DIR}/src/global_util/dbus) + function(generation_snipe_dbus_interface xml class_file) + set(file_name ${XML2CPP_DIR}/${class_file}) + execute_process( + COMMAND ${DTK_XML2CPP} -p ${file_name} ${xml} + WORKING_DIRECTORY ${XML2CPP_DIR} + ) + endfunction() + + set(DBUS_INTERFACES + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Authenticate1.xml authenticate1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Accounts1.xml accounts1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Accounts1.User.xml userinterface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.ImageEffect1.xml imageeffect1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Logined.xml loginedinterface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.SystemPower1.xml systempower1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/com.deepin.wm.xml wminterface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.Authenticate1.Session2.xml session2interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.SessionManager1.xml sessionmanager1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.deepin.dde.SystemDisplay1.xml systemdisplay1interface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.freedesktop.DBus.xml dbusinterface" + "${CMAKE_SOURCE_DIR}/xml/snipe/org.freedesktop.login1.session.self.xml selfinterface" + ) + + foreach(interface IN LISTS DBUS_INTERFACES) + string(REPLACE " " ";" interface_list "${interface}") + + list(GET interface_list 0 XML_FILE) + list(GET interface_list 1 CLASS_FILE) + + list(LENGTH interface_list list_len) + if(list_len LESS 2) + message(FATAL_ERROR "Invalid DBus interface definition: ${interface}") + endif() + + generation_snipe_dbus_interface(${XML_FILE} ${CLASS_FILE}) + endforeach() +endif () + include_directories(${PROJECT_SOURCE_DIR}/src/global_util) include_directories(${PROJECT_SOURCE_DIR}/src/global_util/dbus) include_directories(${PROJECT_SOURCE_DIR}/src/global_util/keyboardmonitor) +include_directories(${PROJECT_SOURCE_DIR}/src/global_util/plugin_manager) include_directories(${PROJECT_SOURCE_DIR}/src/widgets) include_directories(${PROJECT_SOURCE_DIR}/src/session-widgets) include_directories(${PROJECT_SOURCE_DIR}/src/libdde-auth) include_directories(${PROJECT_SOURCE_DIR}/interface) +include_directories(${PROJECT_SOURCE_DIR}/src/global_util/dbus/types) aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util GLOBAL_UTILS) aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util/dbus GLOBAL_UTILS_DBUS) -aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util/keyboardmonitor GLOBAL_UTILS_KEYBOARDMONITOR) aux_source_directory(${PROJECT_SOURCE_DIR}/src/widgets WIDGETS) aux_source_directory(${PROJECT_SOURCE_DIR}/src/session-widgets SESSION_WIDGETS) -aux_source_directory(${PROJECT_SOURCE_DIR}/src/libdde-auth AUTHENTICATE) +## 需要把libdde-auth中的.h编译出moc文件,故采用这种方式 +file(GLOB AUTHENTICATE ${PROJECT_SOURCE_DIR}/src/libdde-auth/*.h ${PROJECT_SOURCE_DIR}/src/libdde-auth/*.cpp) +aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util/keyboardmonitor GLOBAL_UTILS_KEYBOARDMONITOR) aux_source_directory(${PROJECT_SOURCE_DIR}/interface INTERFACE) +aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util/dbus/types DBUS_DATA_TYPES) +aux_source_directory(${PROJECT_SOURCE_DIR}/src/global_util/plugin_manager PLUGIN_MANAGER) set(QRCS ${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc @@ -121,91 +236,127 @@ set(QRCS ) set(LOCK_SRCS - ${authority_DBUS_SCRS} - ${transaction_DBUS_SCRS} + ${AUTH_DBUS_SCRS} + ${SWITCHOS_DBUS_SCRS} + ${SYSTEMD_DISPLAY1_DBUS_SCRS} ${GLOBAL_UTILS} ${GLOBAL_UTILS_DBUS} ${GLOBAL_UTILS_KEYBOARDMONITOR} ${WIDGETS} ${SESSION_WIDGETS} - ${haweiswitchos_DBUS_SCRS} ${AUTHENTICATE} ${INTERFACE} + ${DBUS_DATA_TYPES} + ${PLUGIN_MANAGER} src/app/dde-lock.cpp src/dde-lock/lockframe.cpp src/dde-lock/lockworker.cpp + src/dde-lock/updateworker.cpp + src/dde-lock/securityloaderhelper.cpp src/dde-lock/dbus/dbuslockagent.cpp src/dde-lock/dbus/dbuslockfrontservice.cpp src/dde-lock/dbus/dbusshutdownagent.cpp src/dde-lock/dbus/dbusshutdownfrontservice.cpp + src/widgets/passworderrortipswidget.cpp + src/widgets/passworderrortipswidget.h + src/global_util/dbusconstant.h + src/global_util/signal_bridge.h ) + +link_libraries( + Threads::Threads +) + add_executable(dde-lock ${LOCK_SRCS} ${QRCS} ) + target_include_directories(dde-lock PUBLIC ${PAM_INCLUDE_DIR} - ${DTKWIDGET_INCLUDE_DIR} - ${DTKCORE_INCLUDE_DIR} ${XCB_EWMH_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} - ${QGSettings_INCLUDE_DIRS} - ${Qt5X11Extras_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/dde-lock ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus ) +if (DISABLE_DSS_SNIPE) + target_include_directories(dde-lock PUBLIC + ${DTKWIDGET_INCLUDE_DIR} + ${DTKCORE_INCLUDE_DIR} + ${DFrameworkDBus_INCLUDE_DIRS} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ${Qt5X11Extras_INCLUDE_DIRS} + ) +endif () + target_link_libraries(dde-lock PRIVATE ${Qt_LIBS} ${PAM_LIBRARIES} ${XCB_EWMH_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} - ${DtkWidget_LIBRARIES} - ${DtkCore_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Concurrent_LIBRARIES} - ${Qt5X11Extras_LIBRARIES} - ${Qt5DBus_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${QGSettings_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Widget + Dtk${DTK_VERSION_MAJOR}::Core + ${Greeter_LIBRARIES} + PkgConfig::SSL ) +if (DISABLE_DSS_SNIPE) + target_link_libraries(dde-lock PRIVATE + ${DFrameworkDBus_LIBRARIES} + ${QGSettings_LIBRARIES} + KF5::WaylandClient + ) +endif() set(GREETER_SRCS - ${authority_DBUS_SCRS} - ${transaction_DBUS_SCRS} + ${AUTH_DBUS_SCRS} + ${SWITCHOS_DBUS_SCRS} ${GLOBAL_UTILS} ${GLOBAL_UTILS_DBUS} ${GLOBAL_UTILS_KEYBOARDMONITOR} ${WIDGETS} ${SESSION_WIDGETS} - ${haweiswitchos_DBUS_SCRS} ${AUTHENTICATE} ${INTERFACE} + ${DBUS_DATA_TYPES} + ${PLUGIN_MANAGER} src/app/lightdm-deepin-greeter.cpp src/lightdm-deepin-greeter/loginwindow.cpp src/lightdm-deepin-greeter/greeterworker.cpp src/lightdm-deepin-greeter/logincontent.cpp src/lightdm-deepin-greeter/logintipswindow.cpp src/lightdm-deepin-greeter/sessionwidget.cpp + src/global_util/signal_bridge.h ) + +if (USE_DEEPIN_WAYLAND) + set(GREETER_SRCS + ${GREETER_SRCS} + ) +endif(USE_DEEPIN_WAYLAND) + add_executable(lightdm-deepin-greeter ${GREETER_SRCS} ${QRCS} ) + target_include_directories(lightdm-deepin-greeter PUBLIC ${PAM_INCLUDE_DIR} - ${DTKWIDGET_INCLUDE_DIR} - ${DTKCORE_INCLUDE_DIR} ${XCB_EWMH_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} - ${QGSettings_INCLUDE_DIRS} - ${Qt5X11Extras_INCLUDE_DIRS} ${Greeter_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter ) +if (DISABLE_DSS_SNIPE) + target_include_directories(lightdm-deepin-greeter PUBLIC + ${DTKWIDGET_INCLUDE_DIR} + ${DTKCORE_INCLUDE_DIR} + ${DFrameworkDBus_INCLUDE_DIRS} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ${Qt5X11Extras_INCLUDE_DIRS} + ) +endif () + target_compile_definitions(lightdm-deepin-greeter PRIVATE ENABLE_SESSION ) @@ -220,60 +371,137 @@ target_link_libraries(lightdm-deepin-greeter PRIVATE ${Qt_LIBS} ${PAM_LIBRARIES} ${XCB_EWMH_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} - ${DtkWidget_LIBRARIES} - ${DtkCore_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Concurrent_LIBRARIES} - ${Qt5X11Extras_LIBRARIES} - ${Qt5DBus_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${QGSettings_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Widget + Dtk${DTK_VERSION_MAJOR}::Core ${Greeter_LIBRARIES} + PkgConfig::SSL ) -# debug模式下增加示例demo的编译 -if ((${CMAKE_BUILD_TYPE} MATCHES "Debug")) - add_subdirectory(modules) -endif () +if (DISABLE_DSS_SNIPE) + target_link_libraries(lightdm-deepin-greeter PRIVATE + ${DFrameworkDBus_LIBRARIES} + ${QGSettings_LIBRARIES} + KF5::WaylandClient + ) +endif() -add_subdirectory(tests) +add_executable(greeter-display-setting + src/app/greeter-display-setting.cpp +) -# Install settings -if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX /usr) +target_link_libraries(greeter-display-setting + ${Qt_LIBS} + ${XCB_EWMH_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Core +) + +if (DISABLE_DSS_SNIPE) + add_subdirectory(lighter-greeter) +endif () +add_subdirectory(tests) +add_subdirectory(plugins) +add_subdirectory(src/pam-inhibit-autologin) + +if (DISABLE_DSS_SNIPE) + # bin + install(PROGRAMS files/deepin-greeter DESTINATION ${CMAKE_INSTALL_BINDIR}) + + # install x files + file(GLOB SCRIPTS + files/x/00-xrandr + files/x/10-cursor-theme + files/x/lightdm-deepin-greeter + ) + install(PROGRAMS ${SCRIPTS} DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/greeters.d/x) + # 选择需要执行的二进制 + install(PROGRAMS files/launch-binary DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/greeters.d) + + # install wayland files + install(PROGRAMS files/wayland/launch-kwin-wayland DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/greeters.d/wayland) + install(PROGRAMS files/wayland/lightdm-deepin-greeter-wayland DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/greeters.d/wayland) + install(FILES files/wayland/lightdm-deepin-greeter-wayland.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/xgreeters/) +else () # snipe + install(PROGRAMS files/snipe/deepin-greeter DESTINATION ${CMAKE_INSTALL_BINDIR}) + + file(GLOB SCRIPTS files/snipe/scripts/*) + install(PROGRAMS ${SCRIPTS} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/deepin/greeters.d) endif () -# bin -install(TARGETS dde-lock lightdm-deepin-greeter DESTINATION bin) -install(FILES files/deepin-greeter DESTINATION bin) +# dde-lock binary installed to libexec/deepin for security-loader +install(TARGETS dde-lock DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/deepin) +install(TARGETS lightdm-deepin-greeter greeter-display-setting DESTINATION ${CMAKE_INSTALL_BINDIR}) +# Install loader wrapper script as /usr/bin/dde-lock +install(PROGRAMS files/dde-lock-loader-wrapper DESTINATION ${CMAKE_INSTALL_BINDIR} + RENAME dde-lock + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) -file(GLOB SCRIPTS scripts/*) -install(PROGRAMS ${SCRIPTS} DESTINATION /etc/deepin/greeters.d) +# 指定greeter,优先级最低,允许被其他应用以更高的配置文件覆盖 +install(FILES files/50-deepin.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/lightdm.conf.d) +install(PROGRAMS files/pre-greeter DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/greeters.d) -file(GLOB QM_FILES "translations/*.qm") -install(FILES ${QM_FILES} DESTINATION share/dde-session-shell/translations) -install(FILES qt-theme.ini DESTINATION /etc/lightdm/deepin) +if (DISABLE_DSS_SNIPE) + file(GLOB QM_FILES "translations/*.qm") +endif () +install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/translations) +install(FILES qt-theme.ini DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/lightdm/deepin) + +# desktop +install(FILES files/x/lightdm-deepin-greeter.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/xgreeters/) +if (DISABLE_DSS_SNIPE) + install(FILES files/dde-lock.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/) + install(FILES files/dde-lock.desktop DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/xdg/autostart/) +else () + install(FILES files/snipe/dde-lock.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/) +endif () -install(FILES files/lightdm-deepin-greeter.desktop DESTINATION share/xgreeters/) -install(FILES files/dde-lock.desktop DESTINATION share/applications/) -install(FILES files/dde-session-shell.conf DESTINATION share/dde-session-shell/) -install(FILES files/lightdm-deepin-greeter.conf DESTINATION share/deepin-authentication/privileges/) +# install conf files +if (DDE_SESSION_SHELL_SNIPE) + install(FILES files/dde-session-shell.conf DESTINATION /var/lib/dde-session-shell/) +else() + install(FILES files/dde-session-shell.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-session-shell/) +endif() +install(FILES files/lightdm-deepin-greeter.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/deepin-authentication/privileges/) # services -file(GLOB SERVICES files/*.service) -install(FILES ${SERVICES} DESTINATION share/dbus-1/services) +if (DISABLE_DSS_SNIPE) + file(GLOB SERVICES files/*.service) +else () + file(GLOB SERVICES files/snipe/*.service) +endif () +install(FILES ${SERVICES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dbus-1/services) -#schemas -install(FILES xml/com.deepin.dde.session-shell.gschema.xml DESTINATION share/glib-2.0/schemas) +if (DISABLE_DSS_SNIPE) + #schemas + install(FILES xml/com.deepin.dde.session-shell.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas) +endif () # dev file(GLOB INTERFACE interface/*.h) -install(FILES ${INTERFACE} DESTINATION include/dde-session-shell) +install(FILES ${INTERFACE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dde-session-shell) +configure_file( + ${CMAKE_SOURCE_DIR}/cmake/DdeSessionShellConfig.cmake.in + ${CMAKE_SOURCE_DIR}/cmake/DdeSessionShellConfig.cmake + @ONLY) file(GLOB CMAKE_CONFIG cmake/*.cmake) install(FILES ${CMAKE_CONFIG} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/DdeSessionShell) +# pam +file(GLOB PAM_CONFIG files/pam.d/*) +install(FILES ${PAM_CONFIG} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/pam.d/) + # config -dconfig_meta_files(APPID org.deepin.dde.lock FILES configs/org.deepin.dde.lock.json) -dconfig_meta_files(APPID org.deepin.dde.lightdm-deepin-greeter FILES configs/org.deepin.dde.lightdm-deepin-greeter.json) +if (DISABLE_DSS_SNIPE) + dconfig_meta_files(APPID org.deepin.dde.lock FILES configs/org.deepin.dde.lock.json) + dconfig_meta_files(APPID org.deepin.dde.lightdm-deepin-greeter FILES configs/org.deepin.dde.lightdm-deepin-greeter.json) +else () + dtk_add_config_meta_files(APPID org.deepin.dde.lock FILES configs/snipe/org.deepin.dde.lock.json) + dtk_add_config_meta_files(APPID org.deepin.dde.lightdm-deepin-greeter FILES configs/snipe/org.deepin.dde.lightdm-deepin-greeter.json) + dtk_add_config_meta_files(APPID org.deepin.dde.session-shell FILES configs/snipe/org.deepin.dde.session-shell.json) +endif () + +# debug config file +install(FILES files/deepin-debug-config/org.deepin.dde.session-shell.json + DESTINATION ${CMAKE_INSTALL_DATADIR}/deepin-debug-config/deepin-debug-config.d) +install(FILES files/deepin-log-config/org.deepin.dde.session-shell.json + DESTINATION ${CMAKE_INSTALL_DATADIR}/deepin-log-viewer/deepin-log.conf.d) diff --git a/LICENSES/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt new file mode 100644 index 00000000..13ca539f --- /dev/null +++ b/LICENSES/CC-BY-4.0.txt @@ -0,0 +1,156 @@ +Creative Commons Attribution 4.0 International + + Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. + +Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors. + +Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public. + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. + +Section 1 – Definitions. + + a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + + d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. + + g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. + + i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + + 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. + + 5. Downstream recipients. + + A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. + + B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + + 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). + +b. Other rights. + + 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this Public License. + + 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified form), You must: + + A. retain the following if it is supplied by the Licensor with the Licensed Material: + + i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + + C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. + + 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; + + b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + + a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. + + b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. + + c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + + a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + + c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. + + d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. + +Section 8 – Interpretation. + + a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. + + c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. + + d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 100644 index 00000000..f6cdd22a --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1,232 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on the Program. + +To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. + + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +7. Additional Terms. +“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +11. Patents. +A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. + +You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSES/LGPL-3.0-or-later.txt b/LICENSES/LGPL-3.0-or-later.txt new file mode 100644 index 00000000..513d1c01 --- /dev/null +++ b/LICENSES/LGPL-3.0-or-later.txt @@ -0,0 +1,304 @@ +GNU LESSER GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + +As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. + +"The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. + +An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. + +A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". + +The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. + +The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. +You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. +If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: + + a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. +The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license document. + +4. Combined Works. +You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license document. + + c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. + + e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) + +5. Combined Libraries. +You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. +The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. + +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on the Program. + +To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. + + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +7. Additional Terms. +“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +11. Patents. +A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. + +You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/README.md b/README.md index 96094018..54666f7e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,35 @@ DDE session shell provides two applications: dde-lock and lightdm-deepin-greeter. dde-lock provides screen lock function, and lightdm-deepin-greeter provides login function. -## Build +## Dependencies +You can also check the "Depends" provided in the `debian/control` file. -debian/rules +### Build dependencies +You can also check the "Build-Depends" provided in the `debian/control` file. + +## Installation + +### Build from source code + +1. Make sure you have installed all dependencies. +```bash +sudo apt build-dep dde-session-shell +``` + +2. Build +```bash +mkdir build +cd build +cmake .. +make +``` + +3. Install +```bash +sudo make install +``` + +4. debian/rules ```makefile override_dh_auto_configure: @@ -13,20 +39,20 @@ override_dh_auto_configure: ``` lightdm-deepin-greeter strongly relies on the com.deepin.daemon.Accounts service(created by dde-system-daemon). We use WAIT_DEEPIN_ACCOUNTS_SERVICE to control whether to wait for the service to start when the program starts. If dde-system-daemon will not be started in the desktop environment, please set this value to 0, otherwise the deepin-lightdm-greeter will get stuck. - ## Getting help Any usage issues can ask for help via -* [Gitter](https://gitter.im/orgs/linuxdeepin/rooms) -* [IRC channel](https://webchat.freenode.net/?channels=deepin) +* [Matrix](https://matrix.to/#/#deepin-community:matrix.org) +* [WiKi](https://wiki.deepin.org) * [Forum](https://bbs.deepin.org) -* [WiKi](https://wiki.deepin.org/) +* [Developer Center]((https://github.com/linuxdeepin/developer-center/issues)) ## Getting involved We encourage you to report issues and contribute changes -[**Contribution guide for developers**](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers-en) (English) +- [**Contribution guide for developers**](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers-en) -[**开发者代码贡献指南**](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers) (中文) +## License +DDE session shell is licensed under [GPL-3.0-or-later](LICENSE). \ No newline at end of file diff --git a/README.zh_CN.md b/README.zh_CN.md new file mode 100644 index 00000000..a9dcf753 --- /dev/null +++ b/README.zh_CN.md @@ -0,0 +1,58 @@ +# DDE Session Shell + +DDE session shell 提供两个应用程序:dde-lock 和 lightdm-deepin-greeter,dde-lock提供锁屏界面,lightdm-deepin-greeter提供登录界面。 + +## 依赖 +请查看“debian/control”文件中提供的“Depends”。 + +### 编译依赖 +请查看“debian/control”文件中提供的“Build-Depends”。 + +## 安装 + +### 构建过程 + +1. 确保已经安装了所有的编译依赖 +```bash +sudo apt build-dep dde-session-shell +``` + +2. 构建 +```bash +mkdir build +cd build +cmake .. +make +``` + +3. 安装 +```bash +sudo make install +``` + +4. debian/rules + +```makefile +override_dh_auto_configure: + dh_auto_configure -- \ + -DWAIT_DEEPIN_ACCOUNTS_SERVICE=1 +``` +lightdm-deepin-greeter 强依赖 com.deepin.daemon.Accounts 服务 (由dde-system-daemon创建)。 +我们使用 WAIT_DEEPIN_ACCOUNTS_SERVICE 来判断 lightdm-deepin-greeter 的启动是否等待dde-system-daemon,如果桌面环境没有启动dde-system-daemon,请设置 WAIT_DEEPIN_ACCOUNTS_SERVICE 为 0,否则 deepin-lightdm-greeter 会卡住。 + +## 帮助 +任何使用问题都可以通过以下方式寻求帮助: + +* [Matrix](https://matrix.to/#/#deepin-community:matrix.org) +* [WiKi](https://wiki.deepin.org) +* [官方论坛](https://bbs.deepin.org) +* [开发者中心](https://github.com/linuxdeepin/developer-center/issues) + +## 贡献指南 + +我们鼓励您报告问题并做出更改 + +- [开发者代码贡献指南](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers) + +## 开源许可证 +DDE session shell 在 [GPL-3.0-or-later](LICENSE) 下发布。 diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 00000000..196fd21a --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,88 @@ +version = 1 +SPDX-PackageName = "dde-session-shell" +SPDX-PackageSupplier = "UnionTech Software Technology Co., Ltd." +SPDX-PackageDownloadLocation = "https://github.com/linuxdeepin/dde-session-shell" + +[[annotations]] +path = ["README.md", "README.zh_CN.md"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC-BY-4.0" + +[[annotations]] +path = ["cmake/**.in", "cmake/**.cmake"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "src/global_util/dbus/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "The Qt Company Ltd." +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ["**.pro", "**.qrc", "**CMakeLists.txt", "**.cmake", "qt-theme.ini", "files/**", "scripts/**", "src/lightdm-deepin-greeter/deepin-greeter", ".project", ".syncexclude"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "docs/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "UnionTech Software Technology Co., Ltd." +SPDX-License-Identifier = "GPL-3.0-or-later" + +[[annotations]] +path = ["src/widgets/img/**", "misc/images/**", "src/session-widgets/img/**", "plugins/examples/login-plugins/login-udcp/images/**", "plugins/login-gesture/icons/**", "plugins/login-gesture/resetDialog/success.svg"] +precedence = "aggregate" +SPDX-FileCopyrightText = "UnionTech Software Technology Co., Ltd." +SPDX-License-Identifier = "GPL-3.0-or-later" + +[[annotations]] +path = ["translations/**", "plugins/login-gesture/translations/**", ".tx/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = "UnionTech Software Technology Co., Ltd." +SPDX-License-Identifier = "GPL-3.0-or-later" + +[[annotations]] +path = ["lupdate.sh", "tests/test-recoverage.sh", "translate_generation.sh", "plugins/login-gesture/lupdate.sh", "plugins/login-gesture/translate_generation.sh"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ".gitignore" +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = [".github/**", ".gitlab-ci.yml", ".obs/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = ["xml/**.xml", "**.json", "**.conf"] +precedence = "aggregate" +SPDX-FileCopyrightText = "UnionTech Software Technology Co., Ltd." +SPDX-License-Identifier = "GPL-3.0-or-later" + +[[annotations]] +path = "src/widgets/skin/**.qss" +precedence = "aggregate" +SPDX-FileCopyrightText = "UnionTech Software Technology Co., Ltd." +SPDX-License-Identifier = "GPL-3.0-or-later" + +[[annotations]] +path = ["debian/**", "rpm/**", "archlinux/**"] +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" + +[[annotations]] +path = "toolGenerate/**/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "None" +SPDX-License-Identifier = "CC0-1.0" diff --git a/archlinux/PKGBUILD b/archlinux/PKGBUILD new file mode 100644 index 00000000..9339b706 --- /dev/null +++ b/archlinux/PKGBUILD @@ -0,0 +1,35 @@ +# Maintainer: justforlxz +pkgname=deepin-session-shell-git +pkgver=5.5.9.r123.gd52f772 +pkgrel=1 +sourcename=dde-session-shell +sourcetar="$sourcename"_"$pkgver".tar.xz +sourcedir="$sourcename" +pkgdesc='Deepin desktop-environment - session-shell module' +arch=('x86_64' 'aarch64') +url="https://github.com/linuxdeepin/dde-session-shell" +license=('GPL3') +depends=('deepin-daemon-git' 'deepin-wallpapers-git' 'gsettings-qt' 'liblightdm-qt5' 'startdde-git' 'kwayland5' 'qt5-wayland' 'dtkcore-git' 'dtkwidget-git' 'deepin-pw-check-git') +makedepends=('git' 'cmake' 'ninja' 'qt5-tools' 'gtest' 'gmock' 'dtkcommon-git') +conflicts=('deepin-session-ui<5' 'deepin-session-shell') +provides=('lightdm-deepin-greeter' 'deepin-session-shell') +groups=('deepin-git') +source=($sourcetar) +sha512sums=('SKIP') + +prepare() { + cd $sourcedir + sed -i 's/5\.5//g' CMakeLists.txt tests/lightdm-deepin-greeter/CMakeLists.txt tests/dde-lock/CMakeLists.txt +} + +build() { + cd $sourcedir + cmake . -GNinja -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_SYSCONFDIR=/etc + ninja +} + +package() { + cd $sourcedir + DESTDIR="$pkgdir" ninja install + chmod +x "$pkgdir"/usr/bin/deepin-greeter +} diff --git a/cmake/DdeSessionShellConfig.cmake b/cmake/DdeSessionShellConfig.cmake index 5a06981e..e082e222 100644 --- a/cmake/DdeSessionShellConfig.cmake +++ b/cmake/DdeSessionShellConfig.cmake @@ -1,2 +1,2 @@ -set(DDESESSIONSHELL_INCLUDE_DIR /usr/include/dde-session-shell) +set(DDESESSIONSHELL_INCLUDE_DIR /usr/local/include/dde-session-shell) include_directories(${DDESESSIONSHELL_INCLUDE_DIR}) diff --git a/cmake/DdeSessionShellConfig.cmake.in b/cmake/DdeSessionShellConfig.cmake.in new file mode 100644 index 00000000..5a26728f --- /dev/null +++ b/cmake/DdeSessionShellConfig.cmake.in @@ -0,0 +1,2 @@ +set(DDESESSIONSHELL_INCLUDE_DIR @CMAKE_INSTALL_FULL_INCLUDEDIR@/dde-session-shell) +include_directories(${DDESESSIONSHELL_INCLUDE_DIR}) diff --git a/configs/org.deepin.dde.lightdm-deepin-greeter.json b/configs/org.deepin.dde.lightdm-deepin-greeter.json index 2ea114b3..73fa46c8 100644 --- a/configs/org.deepin.dde.lightdm-deepin-greeter.json +++ b/configs/org.deepin.dde.lightdm-deepin-greeter.json @@ -8,7 +8,7 @@ "flags": ["global"], "name": "UseSolidBackground", "name[zh_CN]": "使用纯色背景", - "description": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", + "description[zh_CN]": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", "permissions": "readwrite", "visibility": "private" }, @@ -18,7 +18,7 @@ "flags": ["global"], "name": "AllowSwitchingToWayland", "name[zh_CN]": "允许用户切换到wayland", - "description": "是否允许用户切换到wayland,默认为否。开启配置时,如果用户安装了wayland和其它桌面环境,登录界面会显示桌面环境切换按钮,点击后用户可以选择wayland桌面环境。关闭配置时,就算用户安装了wayland环境,也会默认隐藏起来,不让用户切换到wayland环境", + "description[zh_CN]": "是否允许用户切换到wayland,默认为否。开启配置时,如果用户安装了wayland和其它桌面环境,登录界面会显示桌面环境切换按钮,点击后用户可以选择wayland桌面环境。关闭配置时,就算用户安装了wayland环境,也会默认隐藏起来,不让用户切换到wayland环境", "permissions": "readwrite", "visibility": "private" }, @@ -28,7 +28,7 @@ "flags": ["global"], "name": "DefaultSessionName", "name[zh_CN]": "默认桌面环境名称", - "description": "默认的桌面环境名称,默认为deepin。新建用户首次登录的时候,默认的桌面由此配置决定", + "description[zh_CN]": "默认的桌面环境名称,默认为deepin。新建用户首次登录的时候,默认的桌面由此配置决定", "permissions": "readwrite", "visibility": "private" }, @@ -38,7 +38,7 @@ "flags": ["global"], "name": "NumLockState", "name[zh_CN]": "数字键盘状态", - "description": "用户的小键盘状态,True为打开,False为关闭,与用户绑定,格式为:\"用户名:状态\",例如\"uos:True\"。当用户改变状态时会记录下来,切换用户时会跟随用户改变。", + "description[zh_CN]": "用户的小键盘状态,True为打开,False为关闭,与用户绑定,格式为:\"用户名:状态\",例如\"uos:True\"。当用户改变状态时会记录下来,切换用户时会跟随用户改变。", "permissions": "readwrite", "visibility": "private" }, @@ -48,9 +48,269 @@ "flags": ["global"], "name": "HideOnboard", "name[zh_CN]": "隐藏屏幕键盘", - "description": "登录界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false;", + "description[zh_CN]": "登录界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "enableOneKeylogin":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "EnableOneKeylogin", + "name[zh_CN]": "是否加载华为自动登录插件", + "description[zh_CN]": "华为了电脑一键登录是否加载插件;false:不加载,true:加载。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultScaleFactors":{ + "value": 1, + "serial": 0, + "flags": ["global"], + "name": "DefaultScaleFactors", + "name[zh_CN]": "登录页面默认缩放", + "description[zh_CN]": "配置greeter界面默认的缩放比例", + "permissions": "readwrite", + "visibility": "private" + }, + "showTopTip":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "showTopTip", + "name[zh_CN]": "是否显示顶部的提示信息,默认不开启", + "description[zh_CN]": "顶部提示信息一般用于定制项目,主线默认不开启", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipText":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "topTipText", + "name[zh_CN]": "顶部的提示信息的文案", + "description[zh_CN]": "顶部的提示信息的文案,不支持多语言", + "permissions": "readwrite", + "visibility": "private" + }, + "showUserName":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "showUserName", + "name[zh_CN]": "锁屏是否展示用户名", + "description[zh_CN]": "锁屏是否展示用户名,默认不展示", + "permissions": "readwrite", + "visibility": "private" + }, + "changePasswordForNormalUser":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "changePasswordForNormalUser", + "name[zh_CN]": "密码过期后普通用户是否可以在登录界面修改密码", + "description[zh_CN]": "密码过期后普通用户是否可以在登录界面修改密码,默认允许", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipTextFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "TopTipTextFont", + "name[zh_CN]": "顶部的提示信息的文案的字体大小", + "description[zh_CN]": "顶部的提示信息的文案的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "userFrameMaxWidth":{ + "value": 226, + "serial": 0, + "flags": ["global"], + "name": "UserNameMaxWidth", + "name[zh_CN]": "用户名界面最大宽度", + "description[zh_CN]": "显示用户名界面的最大宽度,默认为226,小于226不生效。开启后根据用户名长度调整宽度,如果无法完整显示则用省略号补充。", + "permissions": "readwrite", + "visibility": "private" + }, + "fullNameFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "FullNameFont", + "name[zh_CN]": "全名的字体大小", + "description[zh_CN]": "设置全名的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultGreeterSession":{ + "value": "x", + "serial": 0, + "flags": ["global"], + "name": "DefaultGreeterSession", + "name[zh_CN]": "Greeter以x还是wayland的模式启动", + "description[zh_CN]": "Greeter以x还是wayland的模式启动,目前仅x和wayland两种模式.部分机型不适用,修改后可能导致登录黑屏,谨慎修改", + "permissions": "readwrite", + "visibility": "private" + }, + "enableLighterGreeter":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "enableLighterGreeter", + "name[zh_CN]": "是否启用轻量Greeter", + "description[zh_CN]": "是否启用轻量Greeter", + "permissions": "readwrite", + "visibility": "private" + }, + "lastUser":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "lastUser", + "name[zh_CN]": "上一次登录的用户", + "description[zh_CN]": "上一次登录的用户,LighterGreeter登录后会保存登录的用户到此配置项目中(避免对外部服务依赖,自行存储),用于下次登录时选择为默认用户", + "permissions": "readwrite", + "visibility": "private" + }, + "pluginBlackList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Plugin black list", + "name[zh_CN]": "插件黑名单", + "description[zh_CN]": "插件黑名单(包括托盘插件和认证插件),在加载插件的阶段进行判断。系统级配置,默认为空,需要重启电脑。数据结构为数组,内部填充字符串(插件的key值)", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPath":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPath", + "name[zh_CN]": "第三方系统logo水印路径", + "description[zh_CN]": "第三方系统logo水印路径,图片最大不超过500k", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPos":{ + "value": "0,0", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPos", + "name[zh_CN]": "第三方系统logo水印位置", + "description[zh_CN]": "第三方系统logo水印位置,系统LOGO右上角为原点,(10,0)表示 OEM LOGO 在系统LOGO右侧水平间隔10像素", + "permissions": "readwrite", + "visibility": "private" + }, + "showSystemVersion":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowSystemVersion", + "name[zh_CN]": "是否显示系统版本", + "description[zh_CN]": "系统版本显示;false:不显示,true:显示。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用哪一种认证插件,优先级最高。默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 designatedLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 defaultLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用的认证插件,优先级最高,会覆盖 defaultLoginPlugins 的值\n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,优先级次于 designatedLoginPlugins \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsDisplayOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin display order", + "name[zh_CN]": "认证插件的优先级", + "description[zh_CN]": "认证插件的显示顺序 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsAuthOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin auth order", + "name[zh_CN]": "认证插件的优先级", + "description[zh_CN]": "认证插件的认证优先级,此配置优先级最高,会覆盖其它的优先级设置 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "showMediaWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowMediaWidget", + "name[zh_CN]": "是否显示多媒体控制界面", + "description": "是否显示多媒体控制界面,true-显示,false-隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "accountExpression":{ + "value": "[a-zA-Z0-9-_@.]+$", + "serial": 0, + "flags": ["global"], + "name": "AccountExpression", + "name[zh_CN]": "账户名命名规则", + "description": "账户名命名规则", + "permissions": "readwrite", + "visibility": "private" + }, + "longPressDisplayPassword":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "LongPressDisplayPassword", + "name[zh_CN]": "是否长按小眼睛显示密码", + "description": "是否长按小眼睛显示密码,true-鼠按长按小眼睛才显示密码,false-鼠标点击一下就一直显示密码", + "permissions": "readwrite", + "visibility": "private" + }, + "mfaSequence":{ + "value": {"userType":"","authSequence":[]}, + "serial": 0, + "flags": ["global"], + "name": "mfaSequence", + "name[zh_CN]": "多因认证时控制前端按认证顺序展示UI", + "description": "userType可用值,all:代表所有用户,adDomain:代表域用户,其它可选还有default、native,authSequence中的数组即代表认证类型的顺序", "permissions": "readwrite", "visibility": "private" } } -} \ No newline at end of file +} diff --git a/configs/org.deepin.dde.lock.json b/configs/org.deepin.dde.lock.json index 78f950d2..78c96fe8 100755 --- a/configs/org.deepin.dde.lock.json +++ b/configs/org.deepin.dde.lock.json @@ -8,7 +8,7 @@ "flags": [], "name": "UseSolidBackground", "name[zh_CN]": "使用纯色背景", - "description": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", + "description[zh_CN]": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", "permissions": "readwrite", "visibility": "private" }, @@ -18,7 +18,7 @@ "flags": [], "name": "AutoExit", "name[zh_CN]": "自动退出", - "description": "是否自动退出,默认为否。开启配置时,那么隐藏界面一分钟就dde-lock进程将自动退出,降低内存占用。关闭配置时,应用将一直驻留在内存中,每次开启速度较快。", + "description[zh_CN]": "是否自动退出,默认为否。开启配置时,那么隐藏界面一分钟就dde-lock进程将自动退出,降低内存占用。关闭配置时,应用将一直驻留在内存中,每次开启速度较快。", "permissions": "readwrite", "visibility": "private" }, @@ -28,7 +28,7 @@ "flags": [], "name": "HideLogoutButton", "name[zh_CN]": "隐藏注销按钮", - "description": "锁屏界面隐藏注销按钮;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", + "description[zh_CN]": "锁屏界面隐藏注销按钮;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", "permissions": "readwrite", "visibility": "private" }, @@ -38,9 +38,269 @@ "flags": [], "name": "HideOnboard", "name[zh_CN]": "隐藏屏幕键盘", - "description": "锁屏界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", + "description[zh_CN]": "锁屏界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", + "permissions": "readwrite", + "visibility": "private" + }, + "enableOneKeylogin":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "EnableOneKeylogin", + "name[zh_CN]": "是否加载华为自动登录插件", + "description[zh_CN]": "华为了电脑一键登录是否加载插件;false:不加载,true:加载。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShortcutForLock":{ + "value": ["Screenshot","Screen Recorder","Full screenshot","WLAN"], + "serial": 0, + "flags": [], + "name": "EnableShortcutForLock", + "name[zh_CN]": "锁屏下启用的快捷键", + "description[zh_CN]": "锁屏下需要启用一些快捷键,修改后非即时生效", + "permissions": "readonly", + "visibility": "private" + }, + "showTopTip":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "ShowTopTip", + "name[zh_CN]": "是否显示顶部的提示信息,默认不开启", + "description[zh_CN]": "顶部提示信息一般用于定制项目,主线默认不开启", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipText":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "TopTipText", + "name[zh_CN]": "顶部的提示信息的文案", + "description[zh_CN]": "顶部的提示信息的文案,不支持多语言", + "permissions": "readwrite", + "visibility": "private" + }, + "showUserName":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "ShowUserName", + "name[zh_CN]": "锁屏是否展示用户名", + "description[zh_CN]": "锁屏是否展示用户名,默认不展示", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipTextFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "TopTipTextFont", + "name[zh_CN]": "顶部的提示信息的文案的字体大小", + "description[zh_CN]": "顶部的提示信息的文案的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "userFrameMaxWidth":{ + "value": 226, + "serial": 0, + "flags": ["global"], + "name": "UserNameMaxWidth", + "name[zh_CN]": "用户名界面最大宽度", + "description[zh_CN]": "显示用户名界面的最大宽度,默认为226,小于226不生效。开启后根据用户名长度调整宽度,如果无法完整显示则用省略号补充。", + "permissions": "readwrite", + "visibility": "private" + }, + "fullNameFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "FullNameFont", + "name[zh_CN]": "全名的字体大小", + "description[zh_CN]": "设置全名的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "pluginBlackList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Plugin black list", + "name[zh_CN]": "插件黑名单", + "description[zh_CN]": "插件黑名单(包括托盘插件和认证插件),在加载插件的阶段进行判断。系统级配置,默认为空,需要重启电脑。数据结构为数组,内部填充字符串(插件的key值)", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPath":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPath", + "name[zh_CN]": "第三方系统logo水印路径", + "description[zh_CN]": "第三方系统logo水印路径,图片最大不超过500k", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPos":{ + "value": "0,0", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPos", + "name[zh_CN]": "第三方系统logo水印位置", + "description[zh_CN]": "第三方系统logo水印位置,系统LOGO右上角为原点,(10,0)表示 OEM LOGO 在系统LOGO右侧水平间隔10像素", + "permissions": "readwrite", + "visibility": "private" + }, + "showSystemVersion":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowSystemVersion", + "name[zh_CN]": "是否显示系统版本", + "description[zh_CN]": "系统版本显示;false:不显示,true:显示。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "delayInhibitIgnoreList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "DelayInhibitIgnoreList", + "name[zh_CN]": "延迟关机忽略列表", + "description[zh_CN]": "延迟关机忽略列表内的应用不在阻止关机列表中显示", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用哪一种认证插件,优先级最高。默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 designatedLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 defaultLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用的认证插件,优先级最高,会覆盖 defaultLoginPlugins 的值\n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,优先级次于 designatedLoginPlugins \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsDisplayOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin display order", + "name[zh_CN]": "认证插件展示的顺序", + "description[zh_CN]": "认证插件的显示顺序 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsAuthOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin auth order", + "name[zh_CN]": "认证插件认证的顺序", + "description[zh_CN]": "认证插件的认证优先级,此配置优先级最高,会覆盖其它的优先级设置 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShellBlack":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "EnableShellBlack", + "name[zh_CN]": "是否打开shell的黑屏模式", + "description": "是否打开shell的黑屏模;false:不开,true:开启。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "visibleShutdownWhenRebootOrShutdown":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "VisibleShutdownWhenRebootOrShutdown", + "name[zh_CN]": "是否在shutdown页面点击关机或重启时,隐藏shutdown页面", + "description": "是否在shutdown页面点击关机或重启时,隐藏shutdown页面;false:隐藏,true:不隐藏。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "showMediaWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowMediaWidget", + "name[zh_CN]": "是否显示多媒体控制界面", + "description": "是否显示多媒体控制界面,true-显示,false-隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "accountExpression":{ + "value": "[a-zA-Z0-9-_@.]+$", + "serial": 0, + "flags": ["global"], + "name": "AccountExpression", + "name[zh_CN]": "账户名命名规则", + "description": "账户名命名规则", + "permissions": "readwrite", + "visibility": "private" + }, + "longPressDisplayPassword":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "LongPressDisplayPassword", + "name[zh_CN]": "是否长按小眼睛显示密码", + "description": "是否长按小眼睛显示密码,true-鼠按长按小眼睛才显示密码,false-鼠标点击一下就一直显示密码", + "permissions": "readwrite", + "visibility": "private" + }, + "mfaSequence":{ + "value": {"userType":"","authSequence":[]}, + "serial": 0, + "flags": ["global"], + "name": "mfaSequence", + "name[zh_CN]": "多因认证时控制前端按认证顺序展示UI", + "description": "userType可用值,all:代表所有用户,adDomain:代表域用户,其它可选还有default、native,authSequence中的数组即代表认证类型的顺序", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShutdownBlackWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "enableShutdownBlackWidget", + "name[zh_CN]": "是否打开关机、重启黑屏界面", + "description": "是否打开关机、重启黑屏界面;false:不开,true:开启。默认值为true;", "permissions": "readwrite", "visibility": "private" } } -} \ No newline at end of file +} diff --git a/configs/snipe/org.deepin.dde.lightdm-deepin-greeter.json b/configs/snipe/org.deepin.dde.lightdm-deepin-greeter.json new file mode 100644 index 00000000..587285b5 --- /dev/null +++ b/configs/snipe/org.deepin.dde.lightdm-deepin-greeter.json @@ -0,0 +1,306 @@ +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "useSolidBackground": { + "value": false, + "serial": 0, + "flags": ["global"], + "name": "UseSolidBackground", + "name[zh_CN]": "使用纯色背景", + "description": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", + "permissions": "readwrite", + "visibility": "private" + }, + "allowSwitchingToWayland": { + "value": true, + "serial": 0, + "flags": ["global"], + "name": "AllowSwitchingToWayland", + "name[zh_CN]": "允许用户切换到wayland", + "description": "是否允许用户切换到wayland,默认为否。开启配置时,如果用户安装了wayland和其它桌面环境,登录界面会显示桌面环境切换按钮,点击后用户可以选择wayland桌面环境。关闭配置时,就算用户安装了wayland环境,也会默认隐藏起来,不让用户切换到wayland环境", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultSession": { + "value": "deepin", + "serial": 0, + "flags": ["global"], + "name": "DefaultSessionName", + "name[zh_CN]": "默认桌面环境名称", + "description": "默认的桌面环境名称,默认为deepin。新建用户首次登录的时候,默认的桌面由此配置决定", + "permissions": "readwrite", + "visibility": "private" + }, + "numLockState": { + "value": [], + "serial": 0, + "flags": ["global"], + "name": "NumLockState", + "name[zh_CN]": "数字键盘状态", + "description": "用户的小键盘状态,True为打开,False为关闭,与用户绑定,格式为:\"用户名:状态\",例如\"uos:True\"。当用户改变状态时会记录下来,切换用户时会跟随用户改变。", + "permissions": "readwrite", + "visibility": "private" + }, + "hideOnboard":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "HideOnboard", + "name[zh_CN]": "隐藏屏幕键盘", + "description": "登录界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "enableOneKeyLogin":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "EnableOneKeyLogin", + "name[zh_CN]": "是否加载华为自动登录插件", + "description[zh_CN]": "华为了电脑一键登录是否加载插件;false:不加载,true:加载。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultScaleFactors":{ + "value": 1, + "serial": 0, + "flags": ["global"], + "name": "DefaultScaleFactors", + "name[zh_CN]": "登录页面默认缩放", + "description[zh_CN]": "配置greeter界面默认的缩放比例", + "permissions": "readwrite", + "visibility": "private" + }, + "showTopTip":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "showTopTip", + "name[zh_CN]": "是否显示顶部的提示信息,默认不开启", + "description[zh_CN]": "顶部提示信息一般用于定制项目,主线默认不开启", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipText":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "topTipText", + "name[zh_CN]": "顶部的提示信息的文案", + "description[zh_CN]": "顶部的提示信息的文案,不支持多语言", + "permissions": "readwrite", + "visibility": "private" + }, + "showUserName":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "showUserName", + "name[zh_CN]": "锁屏是否展示用户名", + "description[zh_CN]": "锁屏是否展示用户名,默认不展示", + "permissions": "readwrite", + "visibility": "private" + }, + "changePasswordForNormalUser":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "changePasswordForNormalUser", + "name[zh_CN]": "密码过期后普通用户是否可以在登录界面修改密码", + "description[zh_CN]": "密码过期后普通用户是否可以在登录界面修改密码,默认允许", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipTextFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "TopTipTextFont", + "name[zh_CN]": "顶部的提示信息的文案的字体大小", + "description[zh_CN]": "顶部的提示信息的文案的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "userFrameMaxWidth":{ + "value": 226, + "serial": 0, + "flags": ["global"], + "name": "UserNameMaxWidth", + "name[zh_CN]": "用户名界面最大宽度", + "description[zh_CN]": "显示用户名界面的最大宽度,默认为226,小于226不生效。开启后根据用户名长度调整宽度,如果无法完整显示则用省略号补充。", + "permissions": "readwrite", + "visibility": "private" + }, + "fullNameFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "FullNameFont", + "name[zh_CN]": "全名的字体大小", + "description[zh_CN]": "设置全名的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultGreeterSession":{ + "value": "x", + "serial": 0, + "flags": ["global"], + "name": "DefaultGreeterSession", + "name[zh_CN]": "Greeter以x还是wayland的模式启动", + "description[zh_CN]": "Greeter以x还是wayland的模式启动,目前仅x和wayland两种模式.部分机型不适用,修改后可能导致登录黑屏,谨慎修改", + "permissions": "readwrite", + "visibility": "private" + }, + "enableLighterGreeter":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "enableLighterGreeter", + "name[zh_CN]": "是否启用轻量Greeter", + "description[zh_CN]": "是否启用轻量Greeter", + "permissions": "readwrite", + "visibility": "private" + }, + "lastUser":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "lastUser", + "name[zh_CN]": "上一次登录的用户", + "description[zh_CN]": "上一次登录的用户,LighterGreeter登录后会保存登录的用户到此配置项目中(避免对外部服务依赖,自行存储),用于下次登录时选择为默认用户", + "permissions": "readwrite", + "visibility": "private" + }, + "pluginBlackList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Plugin black list", + "name[zh_CN]": "插件黑名单", + "description[zh_CN]": "插件黑名单(包括托盘插件和认证插件),在加载插件的阶段进行判断。系统级配置,默认为空,需要重启电脑。数据结构为数组,内部填充字符串(插件的key值)", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPath":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPath", + "name[zh_CN]": "第三方系统logo水印路径", + "description[zh_CN]": "第三方系统logo水印路径,图片最大不超过500k", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPos":{ + "value": "0,0", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPos", + "name[zh_CN]": "第三方系统logo水印位置", + "description[zh_CN]": "第三方系统logo水印位置,系统LOGO右上角为原点,(10,0)表示 OEM LOGO 在系统LOGO右侧水平间隔10像素", + "permissions": "readwrite", + "visibility": "private" + }, + "showSystemVersion":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowSystemVersion", + "name[zh_CN]": "是否显示系统版本", + "description[zh_CN]": "系统版本显示;false:不显示,true:显示。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用哪一种认证插件,优先级最高。默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 designatedLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 defaultLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用的认证插件,优先级最高,会覆盖 defaultLoginPlugins 的值\n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,优先级次于 designatedLoginPlugins \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsDisplayOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin display order", + "name[zh_CN]": "认证插件的优先级", + "description[zh_CN]": "认证插件的显示顺序 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsAuthOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin auth order", + "name[zh_CN]": "认证插件的优先级", + "description[zh_CN]": "认证插件的认证优先级,此配置优先级最高,会覆盖其它的优先级设置 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "showMediaWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowMediaWidget", + "name[zh_CN]": "是否显示多媒体控制界面", + "description": "是否显示多媒体控制界面,true-显示,false-隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "accountExpression":{ + "value": "[a-zA-Z0-9-_@.]+$", + "serial": 0, + "flags": ["global"], + "name": "AccountExpression", + "name[zh_CN]": "账户名命名规则", + "description": "账户名命名规则", + "permissions": "readwrite", + "visibility": "private" + }, + "longPressDisplayPassword":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "LongPressDisplayPassword", + "name[zh_CN]": "是否长按小眼睛显示密码", + "description": "是否长按小眼睛显示密码,true-鼠按长按小眼睛才显示密码,false-鼠标点击一下就一直显示密码", + "permissions": "readwrite", + "visibility": "private" + } + } +} \ No newline at end of file diff --git a/configs/snipe/org.deepin.dde.lock.json b/configs/snipe/org.deepin.dde.lock.json new file mode 100755 index 00000000..a0914868 --- /dev/null +++ b/configs/snipe/org.deepin.dde.lock.json @@ -0,0 +1,296 @@ +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "useSolidBackground": { + "value": false, + "serial": 0, + "flags": [], + "name": "UseSolidBackground", + "name[zh_CN]": "使用纯色背景", + "description": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", + "permissions": "readwrite", + "visibility": "private" + }, + "autoExit": { + "value": false, + "serial": 0, + "flags": [], + "name": "AutoExit", + "name[zh_CN]": "自动退出", + "description": "是否自动退出,默认为否。开启配置时,那么隐藏界面一分钟就dde-lock进程将自动退出,降低内存占用。关闭配置时,应用将一直驻留在内存中,每次开启速度较快。", + "permissions": "readwrite", + "visibility": "private" + }, + "hideLogoutButton":{ + "value": false, + "serial": 0, + "flags": [], + "name": "HideLogoutButton", + "name[zh_CN]": "隐藏注销按钮", + "description": "锁屏界面隐藏注销按钮;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", + "permissions": "readwrite", + "visibility": "private" + }, + "hideOnboard":{ + "value": false, + "serial": 0, + "flags": [], + "name": "HideOnboard", + "name[zh_CN]": "隐藏屏幕键盘", + "description": "锁屏界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false,修改后即时生效。", + "permissions": "readwrite", + "visibility": "private" + }, + "enableOneKeyLogin":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "EnableOneKeyLogin", + "name[zh_CN]": "是否加载华为自动登录插件", + "description[zh_CN]": "华为了电脑一键登录是否加载插件;false:不加载,true:加载。默认值为false;", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShortcutForLock":{ + "value": ["Screenshot","Screen Recorder","Full screenshot"], + "serial": 0, + "flags": [], + "name": "EnableShortcutForLock", + "name[zh_CN]": "锁屏下启用的快捷键", + "description[zh_CN]": "锁屏下需要启用一些快捷键,修改后非即时生效", + "permissions": "readonly", + "visibility": "private" + }, + "showTopTip":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "ShowTopTip", + "name[zh_CN]": "是否显示顶部的提示信息,默认不开启", + "description[zh_CN]": "顶部提示信息一般用于定制项目,主线默认不开启", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipText":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "TopTipText", + "name[zh_CN]": "顶部的提示信息的文案", + "description[zh_CN]": "顶部的提示信息的文案,不支持多语言", + "permissions": "readwrite", + "visibility": "private" + }, + "showUserName":{ + "value": false, + "serial": 0, + "flags": ["global"], + "name": "ShowUserName", + "name[zh_CN]": "锁屏是否展示用户名", + "description[zh_CN]": "锁屏是否展示用户名,默认不展示", + "permissions": "readwrite", + "visibility": "private" + }, + "topTipTextFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "TopTipTextFont", + "name[zh_CN]": "顶部的提示信息的文案的字体大小", + "description[zh_CN]": "顶部的提示信息的文案的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "userFrameMaxWidth":{ + "value": 226, + "serial": 0, + "flags": ["global"], + "name": "UserNameMaxWidth", + "name[zh_CN]": "用户名界面最大宽度", + "description[zh_CN]": "显示用户名界面的最大宽度,默认为226,小于226不生效。开启后根据用户名长度调整宽度,如果无法完整显示则用省略号补充。", + "permissions": "readwrite", + "visibility": "private" + }, + "fullNameFont":{ + "value": 5, + "serial": 0, + "flags": ["global"], + "name": "FullNameFont", + "name[zh_CN]": "全名的字体大小", + "description[zh_CN]": "设置全名的字体大小,默认为5,有效值为0~9,数字越大字体越小。", + "permissions": "readwrite", + "visibility": "private" + }, + "pluginBlackList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Plugin black list", + "name[zh_CN]": "插件黑名单", + "description[zh_CN]": "插件黑名单(包括托盘插件和认证插件),在加载插件的阶段进行判断。系统级配置,默认为空,需要重启电脑。数据结构为数组,内部填充字符串(插件的key值)", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPath":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPath", + "name[zh_CN]": "第三方系统logo水印路径", + "description[zh_CN]": "第三方系统logo水印路径,图片最大不超过500k", + "permissions": "readwrite", + "visibility": "private" + }, + "customLogoPos":{ + "value": "0,0", + "serial": 0, + "flags": ["global"], + "name": "CustomLogoPos", + "name[zh_CN]": "第三方系统logo水印位置", + "description[zh_CN]": "第三方系统logo水印位置,系统LOGO右上角为原点,(10,0)表示 OEM LOGO 在系统LOGO右侧水平间隔10像素", + "permissions": "readwrite", + "visibility": "private" + }, + "showSystemVersion":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowSystemVersion", + "name[zh_CN]": "是否显示系统版本", + "description[zh_CN]": "系统版本显示;false:不显示,true:显示。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "delayInhibitIgnoreList":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "DelayInhibitIgnoreList", + "name[zh_CN]": "延迟关机忽略列表", + "description[zh_CN]": "延迟关机忽略列表内的应用不在阻止关机列表中显示", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用哪一种认证插件,优先级最高。默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 designatedLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugin":{ + "value": "", + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,默认为空,重启后生效。\n(**deprecated**)此配置不推荐使用,使用 defaultLoginPlugins 配置替代", + "permissions": "readwrite", + "visibility": "private" + }, + "designatedLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Designated login plugin", + "name[zh_CN]": "指定的认证插件", + "description[zh_CN]": "指定使用的认证插件,优先级最高,会覆盖 defaultLoginPlugins 的值\n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "defaultLoginPlugins":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Default login plugin", + "name[zh_CN]": "默认的认证插件", + "description[zh_CN]": "默认使用的认证插件,优先级次于 designatedLoginPlugins \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsDisplayOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin display order", + "name[zh_CN]": "认证插件展示的顺序", + "description[zh_CN]": "认证插件的显示顺序 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "loginPluginsAuthOrder":{ + "value": [], + "serial": 0, + "flags": ["global"], + "name": "Login plugin auth order", + "name[zh_CN]": "认证插件认证的顺序", + "description[zh_CN]": "认证插件的认证优先级,此配置优先级最高,会覆盖其它的优先级设置 \n类型:字符串数组,内部填充插件的 key 值\n默认值:空数组\n生效时机:重启后生效", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShellBlack":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "EnableShellBlack", + "name[zh_CN]": "是否打开shell的黑屏模式", + "description": "是否打开shell的黑屏模;false:不开,true:开启。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "visibleShutdownWhenRebootOrShutdown":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "VisibleShutdownWhenRebootOrShutdown", + "name[zh_CN]": "是否在shutdown页面点击关机或重启时,隐藏shutdown页面", + "description": "是否在shutdown页面点击关机或重启时,隐藏shutdown页面;false:隐藏,true:不隐藏。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + }, + "showMediaWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "ShowMediaWidget", + "name[zh_CN]": "是否显示多媒体控制界面", + "description": "是否显示多媒体控制界面,true-显示,false-隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "accountExpression":{ + "value": "[a-zA-Z0-9-_@.]+$", + "serial": 0, + "flags": ["global"], + "name": "AccountExpression", + "name[zh_CN]": "账户名命名规则", + "description": "账户名命名规则", + "permissions": "readwrite", + "visibility": "private" + }, + "longPressDisplayPassword":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "LongPressDisplayPassword", + "name[zh_CN]": "是否长按小眼睛显示密码", + "description": "是否长按小眼睛显示密码,true-鼠按长按小眼睛才显示密码,false-鼠标点击一下就一直显示密码", + "permissions": "readwrite", + "visibility": "private" + }, + "enableShutdownBlackWidget":{ + "value": true, + "serial": 0, + "flags": ["global"], + "name": "enableShutdownBlackWidget", + "name[zh_CN]": "是否打开关机、重启黑屏界面", + "description": "是否打开关机、重启黑屏界面;false:不开,true:开启。默认值为true;", + "permissions": "readwrite", + "visibility": "private" + } + } +} \ No newline at end of file diff --git a/configs/snipe/org.deepin.dde.session-shell.json b/configs/snipe/org.deepin.dde.session-shell.json new file mode 100644 index 00000000..07c75240 --- /dev/null +++ b/configs/snipe/org.deepin.dde.session-shell.json @@ -0,0 +1,138 @@ +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "authResetTime": { + "value": 15000, + "serial": 0, + "flags": [], + "name": "max auth timeout", + "name[zh_CN]": "最大认证超时时间", + "description[zh_CN]": "最大认证超时时间, 默认为15秒认证超时。", + "description": "max auth timeout", + "permissions": "readwrite", + "visibility": "private" + }, + "delayTime": { + "value": 500, + "serial": 0, + "flags": [], + "name": "delayTime", + "name[zh_CN]": "待机休眠休眠延时时间", + "description[zh_CN]": "待机休眠休眠延时时间, 默认为500毫秒。", + "description": "delay time", + "permissions": "readwrite", + "visibility": "private" + }, + "useDeepinAuth": { + "value": true, + "serial": 0, + "flags": [], + "name": "use Deepin Auth", + "name[zh_CN]": "使用Deepin认证", + "description[zh_CN]": "是否使用Deepin认证。", + "description": "use Deepin Auth", + "permissions": "readwrite", + "visibility": "private" + }, + "checkpwd": { + "value": false, + "serial": 0, + "flags": [], + "name": "check password, check password before reboot or shutdown", + "name[zh_CN]": "检查密码, 在重启或关机前检查密码, 定制化配置, 默认false", + "description[zh_CN]": "是否检查密码。", + "description": "check password", + "permissions": "readwrite", + "visibility": "private" + }, + "sleep": { + "value": true, + "serial": 0, + "flags": [], + "name": "AutoExit", + "name[zh_CN]": "sleep", + "description": "sleep, If enabled, suspend operation display, If disabled, suspend operation does not show.", + "description[zh_CN]": "sleep,如果启用,那么待机操作显示,如果禁用,那么待机操作不显示。", + "permissions": "readwrite", + "visibility": "private" + }, + "hibernate": { + "value": true, + "serial": 0, + "flags": [], + "name": "hibernate", + "name[zh_CN]": "休眠", + "description": "If enabled, hibernate operation display, If disabled, hibernate operation does not show.", + "description[zh_CN]": "如果启用,那么休眠操作显示,如果禁用,那么休眠操作不显示。", + "permissions": "readwrite", + "visibility": "private" + }, + "switchUser": { + "value": 1, + "serial": 0, + "flags": [], + "name": "switch user", + "name[zh_CN]": "切换用户", + "description": "0:always show switch user button。1:ondemand show switch user button。2:disabled show switch user button", + "description[zh_CN]": "0:总是显示切换用户按钮。1:按需显示切换用户按钮。2:禁用显示切换用户按钮", + "permissions": "readwrite", + "visibility": "private" + }, + "systemSuspend": { + "value": 0, + "serial": 0, + "flags": [], + "name": "system suspend", + "name[zh_CN]": "系统待机", + "description": "0:Enabled。1:Disabled。2:Hidden", + "description[zh_CN]": "0:启用。1:禁用。2:隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "systemHibernate": { + "value": 0, + "serial": 0, + "flags": [], + "name": "system hibernate", + "name[zh_CN]": "系统待机", + "description": "0:Enabled。1:Disabled。2:Hidden", + "description[zh_CN]": "0:启用。1:禁用。2:隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "systemShutdown": { + "value": 0, + "serial": 0, + "flags": [], + "name": "system shutdown", + "name[zh_CN]": "系统关机", + "description": "0:Enabled。1:Disabled。2:Hidden", + "description[zh_CN]": "0:启用。1:禁用。2:隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "systemLock": { + "value": 0, + "serial": 0, + "flags": [], + "name": "system lock", + "name[zh_CN]": "系统锁屏", + "description": "0:Enabled。1:Disabled。2:Hidden", + "description[zh_CN]": "0:启用。1:禁用。2:隐藏", + "permissions": "readwrite", + "visibility": "private" + }, + "systemReboot": { + "value": 0, + "serial": 0, + "flags": [], + "name": "system reboot", + "name[zh_CN]": "系统重启", + "description": "0:Enabled。1:Disabled。2:Hidden", + "description[zh_CN]": "0:启用。1:禁用。2:隐藏", + "permissions": "readwrite", + "visibility": "private" + } + } +} diff --git a/debian/changelog b/debian/changelog index 6402706d..ebc11220 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,525 @@ +dde-session-shell (6.0.66) unstable; urgency=medium + + * chore: remove deprecated dde-network-dialog + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Tue, 18 Aug 2026 13:26:01 +0800 + +dde-session-shell (6.0.65) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * feat: add var/lib/dde-session-shell to package install list + + -- zhangkun Thu, 16 Jul 2026 21:50:00 +0800 + +dde-session-shell (6.0.64) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * fix: update dde-daemon dependency version constraint + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * chore: Sync by + https://github.com/linuxdeepin/.github/commit/126af434677bcf06252378 + 4e2f8e98ecab832e15 + + -- zhangkun Thu, 09 Jul 2026 21:55:37 +0800 + +dde-session-shell (6.0.63) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Tue, 30 Jun 2026 19:56:05 +0800 + +dde-session-shell (6.0.62) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Tue, 30 Jun 2026 17:34:58 +0800 + +dde-session-shell (6.0.61) unstable; urgency=medium + + * Release 6.0.61 + + -- xionglinlin Fri, 12 Jun 2026 11:43:49 +0800 + +dde-session-shell (6.0.60) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Thu, 11 Jun 2026 21:33:59 +0800 + +dde-session-shell (6.0.59) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Thu, 14 May 2026 22:11:09 +0800 + +dde-session-shell (6.0.58) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Fri, 08 May 2026 15:36:19 +0800 + +dde-session-shell (6.0.57) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * feat(gesture): add KWin interaction logging support Add shared + logging helpers for KWin-related gesture actions and include + package/version context where available. Update finalized event + identifiers for existing display and input device logs. + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Fri, 08 May 2026 15:03:28 +0800 + +dde-session-shell (6.0.56) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Thu, 23 Apr 2026 21:46:37 +0800 + +dde-session-shell (6.0.55) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Thu, 26 Mar 2026 19:40:05 +0800 + +dde-session-shell (6.0.54) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Thu, 12 Mar 2026 21:22:15 +0800 + +dde-session-shell (6.0.53) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- zhangkun Fri, 27 Feb 2026 17:03:15 +0800 + +dde-session-shell (6.0.52) unstable; urgency=medium + + * Release 6.0.52 + + -- zhangkun Thu, 25 Dec 2025 19:31:24 +0800 + +dde-session-shell (6.0.51) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * feat: add reproducible build parameters + + -- zhaoyingzhen Thu, 27 Nov 2025 17:34:37 +0800 + +dde-session-shell (6.0.50) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- caixiangrong Thu, 06 Nov 2025 16:35:16 +0800 + +dde-session-shell (6.0.49) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- wujiangyu Thu, 23 Oct 2025 16:00:57 +0800 + +dde-session-shell (6.0.48) unstable; urgency=medium + + * chore: remove unused Spanish translation files + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Thu, 18 Sep 2025 21:01:20 +0800 + +dde-session-shell (6.0.47) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell (#461) + * sync: from linuxdeepin/dde-session-shell (#459) + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell (#456) + * sync: from linuxdeepin/dde-session-shell + + -- Wang Zichong Fri, 12 Sep 2025 14:01:07 +0800 + +dde-session-shell (6.0.46) unstable; urgency=medium + + * Sync: from linuxdeepin/dde-session-shell + + -- zyz Fri, 05 Sep 2025 09:36:55 +0800 + +dde-session-shell (6.0.45) unstable; urgency=medium + + * Sync: from linuxdeepin/dde-session-shell + + -- zyz Thu, 28 Aug 2025 18:29:17 +0800 + +dde-session-shell (6.0.44) unstable; urgency=medium + + * Sync: from linuxdeepin/dde-session-shell + * Sync: from linuxdeepin/dde-session-shell + - Updated configs/org.deepin.dde.lock.json + * Fix: update homepage url in debian/control + * Sync: from linuxdeepin/dde-session-shell + * Sync: from linuxdeepin/dde-session-shell + + -- zyz Thu, 14 Aug 2025 14:52:01 +0800 + +dde-session-shell (6.0.43) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * chore: remove unused Spanish translation files + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- zyz Fri, 11 Jul 2025 10:32:10 +0800 + +dde-session-shell (6.0.42) unstable; urgency=medium + + * fix: add hardening compiler flags in debian/rules + + -- WuJiangYu Thu, 03 Jul 2025 19:55:52 +0800 + +dde-session-shell (6.0.41) unstable; urgency=medium + + * chore: remove unused Spanish translation files + + -- xionglinlin Mon, 23 Jun 2025 17:04:03 +0800 + +dde-session-shell (6.0.40) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Thu, 12 Jun 2025 19:33:15 +0800 + +dde-session-shell (6.0.39) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Wed, 28 May 2025 17:17:55 +0800 + +dde-session-shell (6.0.38) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Thu, 15 May 2025 21:30:55 +0800 + +dde-session-shell (6.0.37) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Thu, 08 May 2025 17:36:55 +0800 + +dde-session-shell (6.0.36) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Thu, 08 May 2025 17:36:55 +0800 + +dde-session-shell (6.0.35) unstable; urgency=medium + + * chore: remove Depends="pbis-open" + * sync: from linuxdeepin/dde-session-shell + * sync: from linuxdeepin/dde-session-shell + + -- YeShanShan Tue, 29 Apr 2025 15:20:55 +0800 + +dde-session-shell (6.0.34) unstable; urgency=medium + + * sync: from linuxdeepin/dde-session-shell (#406) + + -- zhaoyingzhen Thu, 17 Apr 2025 17:18:35 +0800 + +dde-session-shell (6.0.33) unstable; urgency=medium + + * chore: Synchronize to 107x (#402) + * chore: sync base dde-session-shell repo (#404) + + -- zhaoyingzhen Thu, 10 Apr 2025 14:13:15 +0800 + +dde-session-shell (6.0.32) unstable; urgency=medium + + * chore: remove startdde dependency + + -- fuleyi Wed, 02 Apr 2025 11:28:22 +0800 + +dde-session-shell (6.0.31) unstable; urgency=medium + + * fix: lock window just show background widget (#400) + + -- YeShanShan Thu, 27 Mar 2025 17:50:04 +0800 + +dde-session-shell (6.0.30) unstable; urgency=medium + + * fix: Unable to open control center + * fix: password lineEdit can copy or cut (#398) + + -- zhaoyingzhen Fri, 21 Mar 2025 10:12:01 +0800 + +dde-session-shell (6.0.29) unstable; urgency=medium + + * feat: add systemReboot config + + -- zhangkun Thu, 27 Feb 2025 21:59:07 +0800 + +dde-session-shell (6.0.28) unstable; urgency=medium + + * fix: multiple screens, has lock screen widget is not the right size + + -- Deepin Packages Builder Thu, 20 Feb 2025 15:13:05 +0800 + +dde-session-shell (6.0.27) unstable; urgency=medium + + * chore: adapt to Qt6. + + -- Deepin Packages Builder Thu, 23 Jan 2025 16:38:47 +0800 + +dde-session-shell (6.0.26) unstable; urgency=medium + + * UNRELEASED + + -- Deepin Packages Builder Thu, 09 Jan 2025 16:07:47 +0800 + +dde-session-shell (6.0.25) unstable; urgency=medium + + * fix: turning off 'Unlocking is required to wake up the computer' does not work + * fix: Time text changes with time zone + + -- zsien Fri, 29 Nov 2024 15:36:13 +0800 + +dde-session-shell (6.0.24) unstable; urgency=medium + + * release 6.0.24 + + -- Zhang Kun Thu, 21 Nov 2024 14:46:11 +0800 + +dde-session-shell (6.0.23) unstable; urgency=medium + + * fix: https://pms.uniontech.com/bug-view-277209.html + * fix: https://pms.uniontech.com/bug-view-279953.html + + -- Zhang Kun Fri, 25 Oct 2024 17:51:45 +0800 + +dde-session-shell (6.0.22) unstable; urgency=medium + + * feat: Expose the Visible property of lockFront in DBus interface (#378) + + -- Yutao Meng Wed, 25 Sep 2024 16:44:54 +0800 + +dde-session-shell (6.0.21) unstable; urgency=medium + + * fix: 修复字体字号为20的时候锁屏界面切换用户列表文字被遮挡的问题 + * fix: incorrect scaling of greeter interface on first login + + -- xionglinlin Wed, 19 Jun 2024 14:34:01 +0800 + +dde-session-shell (6.0.20) unstable; urgency=medium + + * fix: greeter unable to start(Issue: https://github.com/linuxdeepin/developer-center/issues/8681) + + -- Zhang Kun Tue, 21 May 2024 15:02:26 +0800 + +dde-session-shell (6.0.19) unstable; urgency=medium + + * launch system-monitor by am dbus + + -- rewine Wed, 08 May 2024 18:24:15 +0800 + +dde-session-shell (6.0.18) unstable; urgency=medium + + * chore: lock button focus policy tweak(Issue: https://github.com/linuxdeepin/developer-center/issues/6876) + * fix: can't login after recreating user(Issue: #6512) + * fix: content margin for user list(Issue: https://github.com/linuxdeepin/developer-center/issues/5704) + * fix: password level hint not visible(Issue: https://github.com/linuxdeepin/developer-center/issues/5588)(Influence: https://github.com/linuxdeepin/dde-session-shell/issues/302) + * fix: alert and hint disappear when hide(Issue: https://github.com/linuxdeepin/developer-center/issues/5622) + + -- Yixue Wang Fri, 22 Mar 2024 15:45:49 +0800 + +dde-session-shell (6.0.17) unstable; urgency=medium + + * fix: trayWidget shouldn't acquire focus + * fix: add runtime dependency `onboard` for dde-session-shell + + -- YuMing He Tue, 30 Jan 2024 10:17:50 +0800 + +dde-session-shell (6.0.16) unstable; urgency=medium + + * fix: switch tty can not lock screen + * fix: default locale for time + * fix: no translation for time in greeter + + -- dengbo Thu, 25 Jan 2024 09:18:05 +0800 + +dde-session-shell (6.0.15) unstable; urgency=medium + + * fix: greeter edition name show error with locale change + * fix: do not use oldam to invoke dbus server + + -- chenhongtao Fri, 05 Jan 2024 14:33:58 +0800 + +dde-session-shell (6.0.14) unstable; urgency=medium + + * fix: start for a long time because of trying to invoke am + + -- chenhongtao Mon, 26 Nov 2023 16:32:52 +0800 + +dde-session-shell (6.0.13) unstable; urgency=medium + + * chore: Adapt time format feature(Issue: #5902) + + -- Deepin Packages Builder Thu, 26 Oct 2023 17:19:19 +0800 + +dde-session-shell (6.0.12) unstable; urgency=medium + + * feat: support no password unlock + + -- chenhongtao Thu, 19 Oct 2023 10:31:18 +0800 + +dde-session-shell (6.0.11) unstable; urgency=medium + + * Release 6.0.11 + + -- Yixue Wang Thu, 07 Sep 2023 11:05:13 +0800 + +dde-session-shell (6.0.10) unstable; urgency=medium + + * feat: use a special pam module + * chore(CI): correct source name and depends + * fix: qdbusxml2cpp-fix not found + * feat: add toggle password button + * chore: Sync by https://github.com/linuxdeepin/.github/commit/559e91167d4919644f37bbcf123eb0651c1528ea(Influence: none) + * chore(CI): Update obs tag build workflow + + -- Yixue Wang Mon, 14 Aug 2023 11:22:34 +0800 + +dde-session-shell (6.0.9) unstable; urgency=medium + + * feat: use configure_file set path in DdeSessionShellConfig.cmake + * fix: incorrect position of auth widget(Issue: https://github.com/linuxdeepin/developer-center/issues/4184) + * fix: incorrect position and size + * fix: shadow error of tips widget(Issue: https://github.com/linuxdeepin/developer-center/issues/4298) + + -- wangyixue Fri, 12 May 2023 16:25:15 +0800 + +dde-session-shell (6.0.8) unstable; urgency=medium + + * fix: aliasing of user avatar(Issue: https://github.com/linuxdeepin/developer-center/issues/3911) + * fix: remove unnecessary margin in mediawidget(Issue: https://github.com/linuxdeepin/dtk/issues/24) + + -- wangyixue Tue, 18 Apr 2023 09:57:34 +0800 + +dde-session-shell (6.0.7) unstable; urgency=medium + + * fix: second click of network won't close + * feat: add module path debug mode + * fix: popup doesn't reset parent + * fix: continue load plugin if not init + * fix: wrong text width for painting + * fix: user popup list doesn't update locale + * fix: acquiring logged in users failed + * fix: black rectangular background of popup + * fix(greeter): remove delay for startSessionSync + * fix: display error of user type + * fix: archlinux build ci + * fix: dependencies on archlinux + * feat: add archlinux build + + -- wangyixue Thu, 30 Mar 2023 14:46:12 +0800 + +dde-session-shell (6.0.6) unstable; urgency=medium + + [ TagBuilder ] + * fix: 暂时屏蔽UnionID重置密码功能(Bug: 182925)(Influence: 通过UniondID重置密码) + + -- zhaoyingzhen Fri, 13 Jan 2023 10:23:19 +0800 + +dde-session-shell (6.0.5.2) unstable; urgency=medium + + [ Deepin Packages Builder ] + * Revert "Revert "feat: 社区版屏蔽显示协议切换入口""(Task: 236183) + + -- caixiangrong Wed, 11 Jan 2023 12:05:22 +0800 + +dde-session-shell (6.0.5.1) unstable; urgency=medium + + * UNRELEASED + + -- zhaoyingzhen Thu, 29 Dec 2022 19:18:07 +0800 + +dde-session-shell (6.0.4) unstable; urgency=medium + + [ TagBuilder ] + * chore: 更新翻译文件(Influence: 无。) + * fix: 解决有些情况下关机阻止界面取消后不回到桌面的情况(Bug: 171541)(Influence: 关机阻止界面退出后的显示。) + * chore: V23接口改造适配(Task: 207483)(Influence: 无) + * feat: 社区版屏蔽显示协议切换入口(Task: 224723)(Influence: 社区版屏蔽显示协议切换入口) + * fix: 修复登录界面缩放错误的问题(Bug: 176397)(Influence: 设置缩放后登录界面和桌面的缩放不一致) + + -- zhaoyingzhen Tue, 13 Dec 2022 19:18:26 +0800 + +dde-session-shell (6.0.3) unstable; urgency=medium + + [ Deepin Packages Builder ] + * fix: 修复修改密码提示异常的问题(Bug: 141575)(Influence: 修改密码功能) + * chore: 更新changelog(Task: 160471)(Influence: 版本号) + * fix: 修复锁屏界面输入正确密码后会再次进入锁屏界面的问题。(Bug: 149269)(Influence: 无) + * feat: 修改登录锁屏右下角切换用户形式为用户列表。(Task: 124693)(Influence: 登录锁屏右下角切换用户按钮功能,以及切换用户。) + * feat: 修改登录锁屏右下角功能按鈕弹框为圆角。(Task: 179023)(Influence: 登录锁屏右下角功能按钮弹窗及相应功能。) + * chore: 同步V23 deepin-daemon 服务名称修改(Influence: 登录锁屏全量功能) + * fix: 修复登录锁屏出现多一个账户的问题。(Bug: 157241)(Influence: 无影响。) + * fix: 修复登录锁屏点击切换用户按钮后,通过键盘上下键可以移动无选中显示和回车无效的问题。(Bug: 154309)(Influence: 无影响。) + * fix: 修复登录锁屏切换用户列表鼠标hover和键盘上下键多个item都有选中背景的问题。(Bug: 162253)(Influence: 无影响。) + * chore: 修改部分英文提示语及配置文件(Influence: 登录锁屏界面文案显示。) + * chore: 更新翻译文件(Influence: 无。) + + -- baodi Wed, 19 Oct 2022 11:47:05 +0800 + +dde-session-shell (6.0.2) unstable; urgency=medium + + [ TagBuilder ] + * fix: 修复wayland环境下自动待机唤醒后锁屏界面解锁后会切换到登陆界面的问题。(Bug: 143619)(Influence: 登录锁屏界面虚拟键盘的显示。) + * fix: 修复登陆框在有无生物认证的情况下头像高度不一致的情况(Bug: 141905)(Influence: 界面显示) + * fix: 修复密码框部分情况下抖动的问题(Bug: 142343)(Influence: 密码框抖动) + * chore: 默认允许切换wayland。(Task: 156593)(Influence: 登录界面显示可切换wayland按钮。) + * fix: 修复锁屏界面切换用户被切换的用户仍创建认证的问题。(Bug: 141817)(Influence: 锁屏切换用户,被切用户占用认证(如占用指纹,导致切到另一用户指纹提示被占用)) + * fix: 修复重置密码界面锁定图标概率性显示边框的问题(Task: 112769)(Influence: 界面显示) + * fix: 修复密码框部分情况下抖动的问题(Bug: 142343)(Influence: 密码框抖动) + * fix: 修复系统自动待机唤醒直接进入桌面后按物理电源键没有响应的问题。(Bug: 142141)(Influence: 锁屏状态错误,导致其他读应用取状态错误。) + * feat: recompile(Influence: recompile) + * chore: openssl依赖修改(Task: 164647)(Influence: 登录认证) + * fix: 重置密码程序启动并连接成功时锁屏界面才释放独占键盘(Bug: 143503)(Influence: 重置密码过程中按快捷键不会切走锁屏) + * fix: 修复重置密码后进入桌面弹keyring弹窗的问题(Bug: 141575)(Influence: keyring弹窗) + + -- caixiangrong Mon, 25 Jul 2022 14:16:38 +0800 + +dde-session-shell (6.0.1) unstable; urgency=medium + + * release 6.0.1 + + -- fanpengcheng Tue, 21 Jun 2022 16:26:58 +0800 + +dde-session-shell (6.0.0.1) unstable; urgency=medium + + * release 6.0.0.1 + + -- Thu, 2 Jun 2022 09:54:15 +0800 + +dde-session-shell (6.0.0.0) unstable; urgency=medium + + * release 6.0.0.0 + + -- Tue, 30 May 2022 18:00:15 +0800 + dde-session-shell (0.0.0) unstable; urgency=medium * Initialize release diff --git a/debian/compat b/debian/compat deleted file mode 100644 index ec635144..00000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/debian/control b/debian/control index c79ce3cb..39b4ff2a 100644 --- a/debian/control +++ b/debian/control @@ -2,51 +2,43 @@ Source: dde-session-shell Section: devel Priority: optional Maintainer: Deepin Sysdev -Build-Depends: debhelper (>= 8.0.0), pkg-config, +Build-Depends: debhelper-compat (=12), pkg-config, cmake, - qtbase5-dev, - liblightdm-qt5-3-dev | liblightdm-qt-dev, + qt6-base-dev, + qt6-svg-dev, + qt6-tools-dev, + liblightdm-qt6-3-dev | liblightdm-qt-dev, libxcb-ewmh-dev, - libqt5x11extras5-dev, - libgsettings-qt-dev, - libqt5svg5-dev, libglib2.0-dev, - libdtkwidget-dev, - libdtkcore5-bin, - qtdeclarative5-dev, - qttools5-dev-tools, - libpam0g-dev,libsystemd-dev, - libdframeworkdbus-dev, + libdtk6widget-dev, + libdtk6core-bin, + libdtk6core-dev, + libpam0g-dev, + libsystemd-dev, deepin-gettext-tools, libxtst-dev, libxcursor-dev, libxrandr-dev, - libdtkcore5-bin, libgtest-dev, libx11-xcb-dev, libssl-dev, - libdtkcore-dev, - qtwebengine5-dev Standards-Version: 3.9.4 -Homepage: http://www.deepin.org/ +Homepage: https://github.com/linuxdeepin/dde-session-shell-snipe Package: dde-session-shell Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${dist:Depends}, deepin-desktop-schemas (>=5.9.14), - libdframeworkdbus2 (>=5.4.10), - dde-daemon (>=5.13.12), - startdde (>=5.8.9), + deepin-security-loader, + dde-daemon (>>6.1.99), x11-xserver-utils, - dbus-x11, deepin-authenticate(>=1.2.27), + libssl3, + libxcb-util0|libxcb-util1, xsettingsd, - libssl-dev, - libxcb-util0 + onboard Provides: lightdm-greeter -Recommends: onboard, - dss-network-plugin, - dde-network-dialog +Recommends: dss-network-plugin Conflicts: dde-workspace, deepin-notifications, dde-session-ui (<< 5.0.0), @@ -64,9 +56,3 @@ Architecture: any Depends: dde-session-shell (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} Description: deepin desktop-environment - dde-session-shell module development files DDE Session Shell module development files of deepin desktop-environment - -Package: deepin-greeter-wayland -Architecture: any -Depends: dde-session-shell (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}, dde-wayland-config -Description: deepin desktop-environment - dde-session-shell module config files - DDE Session Shell module configuration package adapted to the wayland environment for lightdm-deepin-greeter diff --git a/debian/dde-session-shell.install b/debian/dde-session-shell.install index 7b4b7fd5..16e68cb9 100644 --- a/debian/dde-session-shell.install +++ b/debian/dde-session-shell.install @@ -1,3 +1,6 @@ etc usr/bin usr/share +usr/lib/*/security +var/lib/dde-session-shell +usr/libexec/deepin \ No newline at end of file diff --git a/debian/deepin-greeter-wayland.install b/debian/deepin-greeter-wayland.install deleted file mode 100644 index 4d4d295c..00000000 --- a/debian/deepin-greeter-wayland.install +++ /dev/null @@ -1,5 +0,0 @@ -files/wayland/deepin-greeter-wayland usr/bin -files/wayland/lightdm-deepin-greeter-wayland var -files/wayland/lightdm-deepin-greeter-wayland.desktop usr/share/xgreeters -files/wayland/lightdm-deepin-greeter-default-wayland.json usr/share/dsg/configs/org.deepin.dde.lightdm-deepin-greeter -files/wayland/kwin_wayland_helper-wayland usr/bin diff --git a/debian/deepin-greeter-wayland.postinst b/debian/deepin-greeter-wayland.postinst deleted file mode 100644 index 4defb4e9..00000000 --- a/debian/deepin-greeter-wayland.postinst +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -mv /usr/bin/deepin-greeter-wayland /usr/bin/deepin-greeter -mv /var/lightdm-deepin-greeter-wayland /etc/deepin/greeters.d/lightdm-deepin-greeter -mv /usr/share/xgreeters/lightdm-deepin-greeter-wayland.desktop /usr/share/xgreeters/lightdm-deepin-greeter.desktop -mv /usr/share/dsg/configs/org.deepin.dde.lightdm-deepin-greeter/lightdm-deepin-greeter-default-wayland.json /usr/share/dsg/configs/org.deepin.dde.lightdm-deepin-greeter/org.deepin.dde.lightdm-deepin-greeter.json -mv /usr/bin/kwin_wayland_helper-wayland /usr/bin/kwin_wayland_helper diff --git a/debian/rules b/debian/rules index 5cea71e9..cccb2eb2 100755 --- a/debian/rules +++ b/debian/rules @@ -4,35 +4,37 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 export QT_SELECT=5 +export DEB_BUILD_MAINT_OPTIONS = hardening=+all +export DEB_CFLAGS_MAINT_APPEND = -Wall +export DEB_CXXFLAGS_MAINT_APPEND = -Wall +export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-E + +# reproducible编译参数 +DEB_CMAKE_EXTRA_FLAGS += -DCMAKE_SKIP_BUILD_RPATH=ON include /usr/share/dpkg/default.mk SYSTYPE=Desktop SYSTYPE=$(shell cat /etc/deepin-version | grep Type= | awk -F'=' '{print $$2}') %: - dh $@ --parallel + dh $@ ifeq ($(DEB_BUILD_ARCH), mipsel) override_dh_auto_configure: - dh_auto_configure -- LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES + dh_auto_configure -- $(DEB_CMAKE_EXTRA_FLAGS) LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES endif ifeq ($(DEB_BUILD_ARCH), mips64el) override_dh_auto_configure: - dh_auto_configure -- LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES + dh_auto_configure -- $(DEB_CMAKE_EXTRA_FLAGS) LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES endif ifeq ($(DEB_BUILD_ARCH), sw_64) override_dh_auto_configure: - dh_auto_configure -- LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES + dh_auto_configure -- $(DEB_CMAKE_EXTRA_FLAGS) LOCK_NO_QUIT=YES DISABLE_DEMO_VIDEO=YES DISABLE_TEXT_SHADOW=YES DISABLE_ANIMATIONS=YES USE_CURSOR_LOADING_ANI=YES endif override_dh_auto_configure: dh_auto_configure -- \ - -DWAIT_DEEPIN_ACCOUNTS_SERVICE=1 - -ifeq ($(SYSTYPE), Professional) -ifeq ($(DEB_BUILD_ARCH), amd64) -override_dh_gencontrol: - dh_gencontrol -- -Vdist:Depends="pbis-open" -endif -endif + $(DEB_CMAKE_EXTRA_FLAGS) \ + -DWAIT_DEEPIN_ACCOUNTS_SERVICE=1 \ + -DDDE_SESSION_SHELL_SNIPE=1 diff --git a/docs/development-guide.md b/docs/development-guide.md index 20f963f2..49b4ad9e 100644 --- a/docs/development-guide.md +++ b/docs/development-guide.md @@ -1,13 +1,1296 @@ -# dde-session-shell +# 版本变更记录 -- [Development guide](#development-guide) +| 版本 | 修订说明 | 修订人 | 修订时间 | +|:------|:---------|:-------|:-----------| +| V1.0 | 首次提交 | 殷杰 | 2022-05-17 | +| V1.1 | 1. 认证插件版本号更新为 2.0.0
2. 增加基于 JSON 数据的双向通讯方式
3. 认证插件可以自定义登录器的显示内容 | 殷杰 | 2022-05-17 | +| V1.2 | 补充缺失的接口函数和消息协议,优化文档格式和内容 | 殷杰 | 2023-07-22 | -## Development guide +# 概述 -依赖 dde-session-shell-dev 开发包。 +本文档是针对 UOS 登录器插件的开发指南,旨在指导开发人员如何在 UOS 登录器上增加自定义认证方式。插件必须基于 Qt 框架进行开发。 -模块化接口头文件路径: `/usr/include/dde-session-shell`,接口说明参考各接口类中的注释 +**适用读者:** +- 产品经理 +- 设计人员 +- 开发人员 +- 测试人员 -- base_module_interface.h 定义了接口类必须实现且共用的方法,是所有接口类的基类。 -- login_module_interface.h 定义了登录模块必须实现的方法,继承接口基类。 -- tray_module_interface.h 文件定义了右下角区域模块必须实现的方法,继承接口基类。 +# 认证插件功能介绍 + +UOS 系统内置了多种登录认证方式: +- 密码认证 +- UKey 认证 +- 指纹识别 +- 人脸识别 +- 虹膜识别 + +这些认证方式都是在登录器内部实现的。如果需要添加新的认证方式(如二维码登录),又不想与 UOS 登录器代码产生强耦合,可以通过开发认证插件来实现。只需开发一个符合接口规范的动态库,即可为登录器增加新的认证方式,无需修改 UOS 登录器的源代码。 + +## 认证流程 + +认证插件的工作流程如下: + +1. **插件加载**:登录器在开机/注销/锁屏时加载认证插件 +2. **等待输入**:插件等待用户提供认证信息 +3. **验证处理**:插件验证用户提供的信息 +4. **结果返回**:将认证结果返回给登录器 +5. **完成退出**:登录器处理后续的系统登录流程 + +插件只需专注于认证逻辑,无需关心系统登录的具体实现。 + +```plantuml +@startuml 认证流程时序图 +skinparam handwritten false +skinparam monochrome true +skinparam shadowing false +skinparam defaultFontName sans-serif +skinparam sequenceMessageAlign center + +title 认证流程时序图 + +participant 用户 +participant 登录器 +participant 认证插件 + +autonumber +用户 -> 登录器: 开机、注销、锁屏 +登录器 -> 认证插件: 加载认证插件 +登录器 -> 认证插件: 开始认证 +认证插件 -> 认证插件: 等待用户输入 +用户 -> 认证插件: 提交鉴权信息\n(密码/扫码/生物信息等) +认证插件 -> 认证插件: 校验用户信息\n(本地/远程验证) +认证插件 --> 登录器: 鉴权成功 +登录器 -> 登录器: 进入系统 + +@enduml +``` + +## 术语说明 + +登录器:即 UOS 系统中的登录/锁屏软件。 + +登录界面:是指用户开机、重启、注销后看到的 UI 界面,进程名称为 lightdm-deepin-greeter。 + +锁屏界面:是用户按下 Meta+L 快捷键(没有修改快捷键的情况下),或者在电源界面选择"锁定"后看到的 UI 界面,进程名为 dde-lock。 + +登录界面和锁屏界面是两个不同的进程,UI界面非常相似,但是功能和认证流程有很大的区别,在开发和调试的时候需要区分清楚。通过UI界面的`解锁按钮`可以轻松区分:登录界面解锁按钮是`箭头`图标,锁屏界面解锁按钮是`锁型`图标。 + +# 接口使用 + +## 开发环境配置 + +### 必需组件 + +1. **开发包安装** + ```bash + sudo apt install dde-session-shell-dev # 版本要求 ≥ 5.5.18 + ``` + +### 头文件说明 + +安装完成后,在 `/usr/include/dde-session-shell/` 目录下会有几个关键头文件: +- `base_module_interface.h`:基础接口定义 +- `login_module_interface.h`:登录相关接口定义 +- `login_module_interface_v2.h`:登录相关接口定义(2.x.x版本) + +> **注意**:开发时只需包含 `login_module_interface_v2.h` 即可,它已经包含了基础接口的定义。 + +## 数据结构参考 + +本节介绍认证插件开发中使用的核心数据结构。 + +### 插件类型相关 + +#### ModuleType + +**说明:** 定义插件的基本类型和功能范围 + +**类型:** 枚举 + +**使用场景:** 在插件初始化时指定类型 + +| 字段 | 值 | 说明 | 使用建议 | +|:-----|:---|:-----|:---------| +| LoginType | 0 | 标准认证插件 | 🟢 默认推荐,适用于大多数认证场景 | +| TrayType | 1 | 托盘插件 | ⚪ 认证插件无需关注 | +| FullManagedLoginType | 2 | 全托管插件 | 🟡 需要完全控制登录流程时使用 | +| IpcAssistLoginType | 3 | IPC辅助登录插件 | 🟡 用于厂商密码插件集成 | +| PasswordExtendLoginType | 4 | 密码扩展插件 | 🟡 需要双重认证时使用 | + +> **注意**:除非有特殊需求,默认使用 `LoginType`。其他类型建议先与 UOS 开发团队确认。 + +### 认证数据相关 + +#### AuthCallbackData + +**说明:** 认证结果回传数据结构 +**类型:** 结构体 +**使用场景:** 在认证完成时向登录器返回结果 + +| 字段 | 类型 | 必填 | 说明 | 示例值 | +|:-----|:-----|:-----|:-----|:-------| +| result | int | 是 | 认证结果 | 1: 成功
其他: 失败 | +| account | string | 是 | 用户账号 | "user123" | +| token | string | 否 | 认证凭据 | "password123" | +| message | string | 否 | 提示信息 | "认证成功" | +| json | string | 否 | 预留的扩展数据字段,暂未使用 | | + +> **安全提示**: +> - 认证失败时应该在message中提供友好的错误提示 +> - 避免在message中包含敏感信息,该字段会在日志中打印出来 + +#### AuthResult + +**说明:** 认证结果状态码 +**类型:** 枚举 +**使用场景:** 在 `AuthCallbackData` 的 result 字段中使用 + +| 状态码 | 值 | 说明 | 使用场景 | +|:-------|:---|:-----|:---------| +| None | 0 | 未知状态 | 初始化或异常情况 | +| Success | 1 | 认证成功 | 用户验证通过 | +| Failure | 2 | 认证失败 | 验证不通过或发生错误 | + +> **最佳实践**: +> - 推荐使用头文件中提供的枚举,而不是直接使用数字 + +#### CustomLoginType + +**说明:** 自定义登录方式类型 +**类型:** 枚举 +**使用场景:** 指定插件提供的登录方式类型 + +| 类型 | 值 | 说明 | 适用场景 | +|:-----|:---|:-----|:---------| +| CLT_Default | 0 | 标准登录 | 🟢 单一认证方式 | +| CLT_MFA | 1 | 多因子认证 | 🟡 需要多重验证 | +| CLT_ThirdParty | 2 | 第三方认证 | 🟡 外部认证服务 | + + +### 回调函数相关 + +#### LoginCallBack + +**说明:** 登录器提供的回调函数集合 +**类型:** 结构体 +**使用场景:** 插件与登录器之间的双向通信 + +| 字段 | 类型 | 说明 | 使用方式 | +|:-----|:-----|:-----|:---------| +| app_data | void* | 登录器上下文 | 仅作为回调参数传递,不要修改 | +| authCallbackFun | AuthCallbackFun | 认证结果回调 | 用于返回认证结果 | +| messageCallbackFunc | MessageCallbackFun | 消息通信回调 | 用于主动发送消息给登录器 | + +> **使用说明**: +> - 保存函数指针的变量必须初始化为空,并在使用指针前进行判空,避免使用空指针或野指针。 + +### 应用类型相关 + +#### AppType + +**说明:** 认证发起方的类型标识 +**类型:** 枚举 +**使用场景:** 区分认证请求来源,采用不同的认证策略 + +| 类型 | 值 | 说明 | 进程信息 | 特点 | +|:-----|:---|:-----|:---------|:-----| +| None | 0 | 异常状态 | - | 表示初始化失败或配置错误 | +| Login | 1 | 登录界面 | `/usr/bin/lightdm-deepin-greeter` | 和lightdm配合有标准化的登录流程 | +| Lock | 2 | 锁屏界面 | `/usr/bin/dde-lock` | 认证完成后隐藏界面,仅此而已 | + +> **处理建议**: +> - 如果在登录界面和锁屏界面有不同的业务逻辑,可以通过这个变量来判断。 + +#### LoadType + +**说明:** 插件加载控制标识 +**类型:** 枚举 +**使用场景:** 控制插件是否被登录器加载 + +| 标识 | 值 | 说明 | 使用场景 | +|:-----|:---|:-----|:---------| +| Load | 0 | 允许加载 | 默认值 | +| Notload | 1 | 禁止加载 | 插件根据自身的业务逻辑不想进行认证,例如:
- 系统环境不支持
- 依赖服务未启动
- 配置文件缺失
- 业务需求等 | + +> **最佳实践**: +> - 在插件构造时检查运行环境 +> - 插件应记录不加载的原因 + +### 认证框架相关 + +#### AuthObjectType + +**说明:** 认证服务提供方类型 +**类型:** 枚举 +**使用场景:** 识别当前使用的认证框架,一般认证插件无需关注 + +| 框架类型 | 值 | 说明 | +|:---------|:---|:-----| +| LightDM | 0 | 显示管理器 | +| DeepinAuthenticate | 1 | 深度认证框架 | + + +### 认证方式相关 + +#### AuthType + +**说明:** 系统支持的认证方式 +**类型:** 枚举(位掩码) +**使用场景:** 指定认证方式或组合多种认证方式 + +| 类型 | 值 | 说明 | +|:-----|:---|:-----| +| AT_None | 0 | 未指定 | +| AT_Password | 1<<0 | 密码认证 | +| AT_Fingerprint | 1<<1 | 指纹识别 | +| AT_Face | 1<<2 | 人脸识别 | +| AT_ActiveDirectory | 1<<3 | AD域认证 | +| AT_Ukey | 1<<4 | UKey认证 | +| AT_FingerVein | 1<<5 | 指静脉识别 | +| AT_Iris | 1<<6 | 虹膜识别 | +| AT_Passkey | 1<<7 | 安全密钥 | +| AT_Pattern | 1<<8 | 图案解锁 | +| AT_PAM | 1<<29 | PAM认证 | +| AT_Custom | 1<<30 | 自定义认证 | +| AT_All | -1 | 支持所有方式 | + +> **使用说明**: +> - 可以通过位运算组合多种认证方式,例如:`AT_Password | AT_Fingerprint` 表示同时支持密码和指纹 +> - 插件的认证方式是 `AT_Custom`。 + +#### AuthState + +**说明:** 认证过程的状态标识 +**类型:** 枚举 +**使用场景:** 跟踪和管理认证流程的各个状态 + +| 字段 | 值 | 说明 | 备注 | +| :--- | :-- | :--------- | :---------------------------------------------------------------------------------- | +| AS_None | -1 | 默认 | | +| AS_Success | 0 | 成功 | 此次认证的最终结果 | +| AS_Failure | 1 | 失败 | 此次认证的最终结果 | +| AS_Cancel | 2 | 取消 | 当认证没有给出最终结果时,调用 End 会出发 Cancel 信号 | +| AS_Timeout | 3 | 超时 | 一些认证设备会有超时状态的设定 | +| AS_Error | 4 | 错误 | | +| AS_Verify | 5 | 验证中 | | +| AS_Exception | 6 | 设备异常 | 当前认证会被 End | +| AS_Prompt | 7 | 设备提示 | | +| AS_Started | 8 | 认证已启动 | 调用 Start 之后,每种成功开启都会发送此信号 | +| AS_Ended | 9 | 认证已结束 | 调用 End 之后,每种成功关闭的都会发送此信号,当某种认证类型被锁定时,也会触发此信号 | +| AS_Locked | 10 | 认证已锁定 | 认证类型已锁定,表示认证类型不可用(从安全角度考虑,失败次数过多时会导致这种情况) | +| AS_Recover | 11 | 设备恢复 | 需要调用 Start 重新开启认证,对应 AS_Exception | +| AS_Unlocked | 12 | 认证解锁 | 认证类型解除锁定,表示可以继续继续使用此认证类型开始认证了 | +| AS_Unknown | 13 | 未知状态 | | +| AS_VerifyCode | 14 | 需要验证码 | | + +### 认证级别相关 + +#### DefaultAuthLevel + +**说明:** 认证方式的优先级设置 +**类型:** 枚举 +**使用场景:** 配置默认的认证方式选择策略 + +| 级别 | 值 | 策略 | 使用建议 | +|:-----|:---|:-----|:---------| +| NoDefault | 0 | 智能选择 | 🟢 推荐使用
- 优先使用上次成功的认证方式
- 无历史记录时按系统默认顺序 | +| Default | 1 | 已废弃 | ⛔ 不要使用
- 保留向后兼容
- 功能与 NoDefault 类似 | +| StrongDefault | 2 | 强制插件 | 🟡 特殊场景
- 始终优先使用插件认证
| + +> **选择建议**: +> - 一般情况使用 `NoDefault`,提供更好的用户体验 +> - 需要强制使用插件认证时,使用 `StrongDefault` +> - 避免使用已废弃的 `Default` 级别 + +## 接口说明 + +在开发认证插件时需要以 public 方式继承LoginModuleInterfaceV2,并实现以下接口。 + +### BaseModuleInterface + +#### type + +**函数定义:** + +```c++ +virtual ModuleType type() const = 0 +``` + +**说明:** 插件的类型。 + +**入参:** 无 + +**返回值:** + +| 类型 | 说明 | 备注 | +| :--------- | :--------- | :------------------------- | +| ModuleType | 插件的类型 | 认证插件必须返回 LoginType | + +**必须实现:** 否;LoginModuleInterface 已经实现了这个函数,默认返回 LoginType。 + +#### init + +**函数定义:** + +```c++ +virtual void init() = 0 +``` + +**说明:** +1. 插件加载是在子线程进行的,界面相关的初始化操作放在这个函数中,不要放在构造函数里处理。 +2. 这个方法在主线程中调用,不要进行耗时操作,耗时操作请异步处理。 +3. 这个函数可能会重复调用,以重置界面内容。 + +**入参:** 无 + +**返回值:** 无 + +**必须实现:** 是 + +#### key + +**函数定义:** + +```c++ +virtual QString key() const = 0 +``` + +**说明:** 唯一值,用于与其它模块区分。 + +**入参:** 无 + +**返回值:** + +| 类型 | 说明 | 备注 | +| :----- | :------- | :----------------------- | +| string | 唯一编码 | 传入与项目相关的命名即可,切记要带有独特性(比如公司、项目缩写),避免和其它插件重名 | + +**必须实现:** 是 + +#### icon + +**函数定义:** + +```c++ +virtual QString icon() const +``` + +**说明:** +当认证因子不止一种时,登录器会显示认证类型切换组件,它是由一个按钮组(Button Group)组成的,此函数返回的图标会展示在"认证插件切换按钮"上面。 + +**入参:** 无 + +**返回值:** + + +| 类型 | 说明 | 备注 | +| :----- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | +| string | 认证插件的图标 | - 使用图标的绝对路径(加载方式为 QIcon("absolute path"))
- 使用系统图标的名称(加载方式为 QIcon::fromTheme("system icon name"))。 | + +**必须实现:** 否 + +#### content + +**函数定义:** + +```c++ +virtual QWidget* content() const = 0 +``` + +**说明:** +登录器会将返回的 QWidget* 内容展示出来,可以展示提示信息或者二维码等,具体内容插件可以自由设计。需要注意的是,登录器的展示的版面有限,高度最好不要超过 500 像素,宽度不超过 900 像素。 + +**入参:** 无 + +**返回值:** + +| 类型 | 说明 | 备注 | +| :-------- | :--------------------- | :--------------------------------- | +| QWidget\* | 插件想要显示的窗口指针 | 由登录器托管,插件不要释放这个指针 | + +**必须实现:** 是 + +#### loadPluginType + +**函数定义:** + +```c++ +virtual LoadType loadPluginType() const +``` + +**说明:** +登录器在加载插件的时候会调用这个接口,如果返回 Load,那么登录会加载插件,返回其它则不会加载插件。 非全平台或全架构的插件需要重新实现这个接口,根据实际情况处理。 + +**入参:** 无 + +**返回值:** + +| 类型 | 说明 | 备注 | +| :------- | :-------------------- | :--- | +| LoadType | 见 `LoadType`的说明 | - | + +**必须实现:** 是 + +#### setAppData + +**函数定义:** + +```c++ +virtual void setAppData(void*) const +``` + +**说明:** +设置登录器的回调指针,插件需要保存指针,在使用回调函数的时候回传给登录器。如果要使用回调函数,则必须实现此函数。函数可能会被重复调用,插件回传最后一次设置的即可。 + +**入参:** + +| 类型 | 说明 | 备注 | +| :----- | :------------------- | :--- | +| void\* | 登录器的回调指针 | - | + +**返回值:** 无 + +**必须实现:** 否 + +#### setMessageCallback + +**函数定义:** + +```c++ +virtual void setMessageCallback(MessageCallbackFunc *) = 0 +``` + +**说明:** 设置回调函数,会在init函数之前调用。 + +**入参:** + +| 类型 | 说明 | 备注 | +| :-------------------- | :----------------------------------- | :--- | +| MessageCallbackFunc\* | 详见 `MessageCallbackFunc`类型说明 | | + +**返回值:** 无 + +**必须实现:** 否 + +#### MessageCallbackFun + +**函数定义:** + +```c++ +QString (*)(const QString &, void *) +``` + +**说明:** +消息回调函数,用于向登录器发起通讯的场景 + +**入参:** + +| 类型 | 说明 | 备注 | +| :----- | :-------------------------------- | :-------------------------------------- | +| string | 发送给登录器的 JSON 格式数据 | JSON 数据的具体内容详见 "JSON 数据协议" 部分 | +| void\* | 即 LoginCallBack 的 app_data 字段 | | + +**返回值:** + +| 类型 | 说明 | 备注 | +| :----- | :--------------------------- | :--- | +| string | 登录器返回的 JSON 格式数据 | | + + + +### LoginModuleInterfaceV2 + +#### message + +**函数定义:** + +```c++ +virtual QString message(const QString &) +``` + +**说明:** +登录器主动向认证插件发起通讯,用于获取插件信息或者给插件提供信息。**这是插件与登录器交互的核心方法**,插件通过处理不同的 JSON 消息来实现各种功能。具体的 JSON 协议格式请参考本文档的 "JSON 数据协议" 部分。 + +**入参:** + +| 类型 | 说明 | 备注 | +| :------ | :-------------- | :--- | +| QString | json 格式字符串 | 包含CmdType等字段的JSON消息 | + +**返回值:** + +| 类型 | 说明 | 备注 | +| :------ | :-------------- | :--- | +| QString | json 格式字符串 | 插件的响应数据 | + +**必须实现:** 否 + +**实现示例:** + +```c++ +QString YourPlugin::message(const QString &jsonStr) { + QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8()); + QJsonObject obj = doc.object(); + QString cmdType = obj["CmdType"].toString(); + + if (cmdType == "IsPluginEnabled") { + QJsonObject response; + response["Code"] = 0; + response["Message"] = "Success"; + QJsonObject data; + data["IsPluginEnabled"] = true; // 插件是否启用 + response["Data"] = data; + return QJsonDocument(response).toJson(); + } else if (cmdType == "GetConfigs") { + // 处理获取配置的请求 + QJsonObject response; + response["Code"] = 0; + response["Message"] = "Success"; + QJsonObject data; + data["ShowAvatar"] = true; + data["ShowUserName"] = true; + data["DefaultAuthLevel"] = 1; + response["Data"] = data; + return QJsonDocument(response).toJson(); + } + // 处理其他命令... + + return "{}"; // 默认返回空JSON对象 +} +``` + + +**必须实现:** 否 + +#### setAuthCallback + +**函数定义:** + +```c++ +virtual void setAuthCallback(AuthCallbackFunc *) = 0 +``` + +**说明:** 设置认证结果回调函数,会在init函数之前调用。 + +**入参:** + +| 类型 | 说明 | 备注 | +| :----------------- | :-------------------------------- | :--- | +| AuthCallbackFunc\* | 详见 `AuthCallbackFunc`类型说明 | | + +**返回值:** 无 + +**必须实现:** 是 + +#### AuthCallbackFun + +**函数定义:** + +```c++ +void (*)(const AuthCallbackData *, void *) +``` + +**说明:** 认证回调函数,用于插件返回认证的状态、结果等 + +**入参:** + +| 类型 | 说明 | 备注 | +| :----------------- | :-------------------------------- | :--- | +| AuthCallbackData\* | 认证相关信息 | | +| void\* | 即 LoginCallBack 的 app_data 字段 | | + +**返回值:** 无 + +#### reset + +**函数定义:** + +```c++ +virtual void reset() = 0 +``` + +**说明:** +插件需要在这个方法中重置UI和验证状态,通常验证开始之前登录器会调用这个方法,但是不保证每次验证前都会调用。插件必须实现这个函数,并在函数内重置之前的验证结果,避免将以前的结果应用在当前认证中。 + +**入参:** 无 + +**返回值:** 无 + +**必须实现:** 是 + +### 初始化接口调用 + +认证插件初始化时接口调用顺序如下: + +```plantuml +@startuml +start +if (loadPluginType() == Load) then (yes) +:setAuthCallback +setMessageCallback +setAppdata] +:init] +:初始化后其它方法都可以会被调用] +else (no) +endif +stop +@enduml + +``` + +## JSON 数据协议 + +插件与登录器之间通过 JSON 格式进行消息交互。这些协议在 `message()` 方法和 `messageCallback()` 函数中使用。 + +### 指令方向说明 + +- **登录器→插件**:登录器主动发送给插件的协议(插件在 `message()` 方法中处理) +- **插件→登录器**:插件主动发送给登录器的协议(插件通过 `messageCallback()` 函数发送) + +### 默认响应格式 + +| 字段 | 类型 | 说明 | +| :------ | :----- | :--------------- | +| Code | int | 0 成功,其他失败 | +| Message | string | 提示消息 | + +示例: + +```json +{ + "Code": 0, + "Message": "Success" +} +``` + +### 🔴 核心协议 + +核心协议是认证插件必须关注的基础通信协议,确保插件能够正常集成到登录系统中。 + +#### IsPluginEnabled(登录器 ⟶ 插件) + +登录器查询插件是否启用。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :---------------- | :--- | +| CmdType | string | "IsPluginEnabled" | 插件没有实现则默认为ture | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :------------------- | :----- | :----- | :--------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.IsPluginEnabled | bool | 是 | 默认为 true | + +**示例:** + +```json +// 请求 +{ + "CmdType": "IsPluginEnabled" +} + +// 响应 +{ + "Code": 0, + "Message": "Success", + "Data": { + "IsPluginEnabled": true + } +} +``` + +#### GetConfigs(登录器 ⟶ 插件) + +登录器获取插件的UI控制配置。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :----------- | :--- | +| CmdType | string | "GetConfigs" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :---------------------- | :----- | :----- | :----------------------------------------------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.ShowAvatar | bool | 否 | 是否显示用户头像 | +| Data.ShowUserName | bool | 否 | 是否显示用户名 | +| Data.ShowSwitchButton | bool | 否 | 是否显示认证类型切换按钮 | +| Data.ShowLockButton | bool | 否 | 是否显示解锁按钮 | +| Data.DefaultAuthLevel | int | 否 | 见`DefaultAuthLevel`枚举说明 | +| Data.SupportDefaultUser | bool | 否 | 是否支持默认用户登录 | + +**示例:** + +```json +// 请求 +{ + "CmdType": "GetConfigs" +} + +// 响应 +{ + "Code": 0, + "Message": "Success", + "Data": { + "ShowAvatar": true, + "ShowUserName": true, + "ShowSwitchButton": true, + "ShowLockButton": false, + "DefaultAuthLevel": 1 + } +} +``` + +#### CurrentUserChanged(用户变化通知) + +登录器通知插件当前用户发生变化。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :-------- | :----- | :----------------- | :----------------- | +| CmdType | string | CurrentUserChanged | | +| Data | object | - | | +| Data.Name | string | - | 当前用户的用户名 | +| Data.Uid | int | - | 当前用户的ID | + +**响应:** 默认响应格式 + +**示例:** + +```json +// 请求 +{ + "CmdType": "CurrentUserChanged", + "Data": { + "Name": "uos", + "Uid": 1001 + } +} +``` + +#### SetAuthTypeInfo(设置认证类型信息) + +插件向登录器发送认证类型相关信息。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +|:-----|:-----|:---|:-----| +| CmdType | string | "setAuthTypeInfo" | ⚠️ 这里首字母是小写(历史原因) | +| Data | object | - | | +| Data.AuthType | int | - | 见 `AuthType` 枚举说明 | + +**示例:** + +```json +// 请求 +{ + "CmdType": "SetAuthTypeInfo", + "Data": { + "AuthType": 1 + } +} +``` + + +### 🟡 扩展协议 + +扩展协议提供额外的功能特性,开发者可根据实际需求选择性实现,用于增强插件的功能表现。 + +#### GetProperties(登录器 ⟶ 插件) + +登录器获取系统属性信息。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :------------------------ | :----------------------------------------------------------- | +| CmdType | string | "GetProperties" | | +| Data | array | ["AppType","CurrentUser"] | 支持的属性列表,API 2.0.0+ 支持 "AppType", "CurrentUser" | + +**响应:** + +| 字段 | 类型 | 说明 | +| :-------------------- | :----- | :-------------------- | +| Code | int | 0 成功,其他失败 | +| Message | string | 提示消息 | +| Data | object | - | +| Data.AppType | int | 详见 AppType 枚举说明 | +| Data.CurrentUser | object | 当前用户信息 | +| Data.CurrentUser.Name | string | 当前用户的用户名 | +| Data.CurrentUser.Uid | int | 当前用户的ID | + +#### StartAuth(登录器 ⟶ 插件) + +登录器通知插件开始认证。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------------------ | :----- | :-------- | :-------------------------- | +| CmdType | string | StartAuth | | +| Data | object | | | +| Data.AuthObjectType | int | | 见 `AuthObjectType`的说明 | + +**响应:** 默认响应格式 + +#### AuthState(登录器 ⟶ 插件) + +登录器发送当前认证状态。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------------- | :----- | :---------- | :----------------------- | +| CmdType | string | "AuthState" | | +| Data | object | | | +| Data.AuthType | int | | 见 `AuthType`的说明 | +| Data.AuthState | int | | 见 `AuthState`的说明 | + +**响应:** 默认响应格式 + +#### LimitsInfo(登录器 ⟶ 插件) + +登录器发送认证限制信息。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :----------------- | :----- | :----------- | :------------------------ | +| CmdType | string | "LimitsInfo" | | +| Data | array | | | +| Object.Flag | int | | 认证类型,见 `AuthType` | +| Object.Locked | bool | | 是否锁定 | +| Object.MaxTries | int | | 可尝试的次数 | +| Object.NumFailures | int | | 已错误次数 | +| Object.UnlockSecs | int | | 还剩多久解锁 | +| Object.UnlockTime | string | | 解锁时间 | + +**响应:** 默认响应格式 + +#### AccountError(登录器 ⟶ 插件) + +登录器通知插件账户验证出现错误。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :------------- | :------------------------------------------------- | +| CmdType | string | "AccountError" | 当账户信息错误的时候会发出这个信息,比如用户不存在,用户密码过期等 | + +**响应:** 默认响应格式 + +#### AuthFactorsChanged(登录器 ⟶ 插件) + +登录器通知插件认证因子发生变化。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :------------------ | :------- | +| CmdType | string | "AuthFactorsChanged" | | +| Data | int | | 认证因子 | + +**响应:** 默认响应格式 + +#### ReadyToAuthChanged(插件 ⟶ 登录器) + +插件通知登录器认证准备状态发生变化。 + +**发送方式:** 插件通过 `messageCallback()` 发送 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :------------------- | :----------- | +| CmdType | string | "ReadyToAuthChanged" | | +| Data | bool | | 是否准备就绪 | + +**响应:** 默认响应格式 + +#### ReadyToAuth(登录器 ⟶ 插件) + +登录器查询插件是否准备好进行认证。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :----------- | :--- | +| CmdType | string | "ReadyToAuth" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :--------------- | :----- | :----- | :--------------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.ReadyToAuth | bool | 是 | 是否准备好认证,默认true | + +### ⚪ 特殊协议 + +特殊协议专门用于处理复杂业务场景和特殊需求,适用于特殊定制化开发,按需实现。 + +#### GetLevel(登录器 ⟶ 插件) + +用于多层级认证场景。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :-------- | :--- | +| CmdType | string | "GetLevel" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :--------- | :----- | :----- | :------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.Level | int | 是 | 插件层级,默认为1 | + +#### GetLoginType(登录器 ⟶ 插件) + +获取插件的登录类型。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :------------ | :--- | +| CmdType | string | "GetLoginType" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :------------- | :----- | :----- | :----------------------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.LoginType | int | 是 | 登录类型,见`CustomLoginType` | + +#### HasSecondLevel(登录器 ⟶ 插件) + +检查指定用户是否需要第二层认证。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :-------------- | :------- | +| CmdType | string | "HasSecondLevel" | | +| Data | string | | 用户名 | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :------------------ | :----- | :----- | :------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.HasSecondLevel | bool | 是 | 是否需要二层认证 | + +#### GetSessionTimeout(登录器 ⟶ 插件) + +获取插件自定义的会话超时时长。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :----------------- | :--- | +| CmdType | string | "GetSessionTimeout" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :------------------ | :----- | :----- | :------------------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.SessionTimeout | int | 是 | 会话超时时长(毫秒),默认15000 | + +#### UpdateLoginType(登录器 ⟶ 插件) + +通知插件更新登录类型,登录类型信息依赖远程配置。 + +**请求:** + +| 字段 | 类型 | 值 | 说明 | +| :------ | :----- | :--------------- | :--- | +| CmdType | string | "UpdateLoginType" | | + +**响应:** + +| 字段 | 类型 | 必填项 | 说明 | +| :------------- | :----- | :----- | :------------------- | +| Code | int | 否 | 0 成功,其他失败 | +| Message | string | 否 | 提示消息 | +| Data | object | 是 | | +| Data.LoginType | int | 是 | 更新后的登录类型 | + +## 编程实例 + +### CMakeLists.txt + +```cmake +# 设置运行此配置所需的 cmake 的最低版本 +cmake_minimum_required(VERSION 3.11) + +# 使用 set 命令设置一个变量 +set(PLUGIN_NAME login-basic) + +# 设置项目名称 +project(${PLUGIN_NAME}) + +# 启用 qt moc 的支持 +set(CMAKE_AUTOMOC ON) +# 启用 qrc 资源文件的支持 +set(CMAKE_AUTORCC ON) + +# 指定所有源码文件 +# 使用了 cmake 的 file 命令,递归查找项目目录下所有头文件和源码文件 +# 并将结果放入 SRCS 变量中,方便后续取用 +file(GLOB_RECURSE SRCS "*.h" "*.cpp") + +# 指定要用到的库 +# 使用了 cmake 的 find_package 命令,查找库 Qt5Widgets 等, +# REQUIRED 参数表示如果没有找到则报错 +# find_package 命令在找到并加载指定的库之后会设置一些变量 +# 常用的有: +# <库名>_FOUND 是否找到(Qt5Widgets_FOUND) +# <库名>_DIR 在哪个目录下找到的(Qt5Widgets_DIR) +# <库名>_INCLUDE_DIRS 有哪些头文件目录(Qt5Widgets_INCLUDE_DIRS) +# <库名>_LIBRARIES 有哪些库文件(Qt5Widgets_LIBRARIES) +find_package(Qt5Widgets REQUIRED) +find_package(DtkWidget REQUIRED) +find_package(DdeSessionShell REQUIRED) + +# find_package 命令还可以用来加载 cmake 的功能模块 +# 并不是所有的库都直接支持 cmake 查找的,但大部分都支持了 pkg-config 这个标准, +# 因此 cmake 提供了间接加载库的模块:FindPkgConfig, 下面这行命令表示加载 FindPkgConfig 模块, +# 这个 cmake 模块提供了额外的基于 "pkg-config" 加载库的能力 +# 执行下面的命令后会设置如下变量,不过一般用不到: +# PKG_CONFIG_FOUND pkg-config 可执行文件是否找到了 +# PKG_CONFIG_EXECUTABLE pkg-config 可执行文件的路径 +# PKG_CONFIG_VERSION_STRING pkg-config 的版本信息 +find_package(PkgConfig REQUIRED) + +# add_definitions 命令用于声明/定义一些编译/预处理参数 +add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") + +# 新增一个编译目标 +# 这里使用命令 add_library 来表示本项目要生成一个库文件目标, +# 类似的还有命令 add_executable 添加一个可执行二进制目标,甚至 add_custom_target(使用较少) 添加自定义目标 +# SHARED 表示生成的库应该是动态库, +# 变量 ${PLUGIN_NAME} 和 ${SRCS} 都是前面处理好的, +# 另外 qrc 资源文件也应该追加在后面以编译进目标中。 +add_library(${PLUGIN_NAME} SHARED ${SRCS}) + +# 设置目标的生成位置,这里表示生成在执行 make 的目录, +# 另外还有很多可用于设置的属性,可查阅 cmake 文档。 +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ./) + +# 设置目标要使用的 include 目录,即头文件目录 +# 变量 ${DtkWidget_INCLUDE_DIRS} 是在前面执行 find_package 命令时引入的 +# 当出现编译失败提示找不到某些库的头文件时应该检查此处是否将所有需要的头文件都包含了 +target_include_directories(${PLUGIN_NAME} PUBLIC + ${Qt5Widgets_INCLUDE_DIRS} + ${DtkWidget_INCLUDE_DIRS} + ${DdeSessionShell_INCLUDE_DIRS} +) + +# 设置目标要使用的链接库 +# 变量 ${DtkWidget_LIBRARIES} 和 ${Qt5Widgets_LIBRARIES} 是在前面执行 find_package 命令时引入的 +# 当出现运行时错误提示某些符号没有定义时应该检查此处是否将所有用的库都写在了这里 +target_link_libraries(${PLUGIN_NAME} PRIVATE + ${Qt5Widgets_LIBRARIES} + ${DtkWidget_LIBRARIES} + ${DdeSessionShell_LIBRARIES} +) + +# 设置安装路径的前缀(默认为"/usr/local") +set(CMAKE_INSTALL_PREFIX "/usr") + +# 设置执行 make install 时哪个目标应该被 install 到哪个位置 +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) + +``` + +### 头文件 + +```c++ +#ifndef LOGIN_MODULE_H +#define LOGIN_MODULE_H + +#include "login_module_interface_v2.h" + +namespace dss { +namespace module_v2 { + +class LoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + +public: + explicit LoginModule(QObject *parent = nullptr); + ~LoginModule() override; + + void init() override; + + inline QString key() const override { return objectName(); } + inline QWidget *content() override { return m_loginWidget; } + void reset() override; + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + QString message(const QString &) override; + +private: + void initUI(); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + QWidget *m_loginWidget; +}; + +} // namespace module_v2 +} // namespace dss +#endif // LOGIN_MODULE_H +``` + +### 源文件 + +```c++ +#include "login_module.h" + +#include +#include +#include +#include +#include +#include + +namespace dss { +namespace module_v2 { + +LoginModule::LoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_loginWidget(nullptr) +{ + setObjectName(QStringLiteral("LoginModule")); +} + +LoginModule::~LoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget; + m_loginWidget = nullptr; + } +} + +void LoginModule::init() +{ + initUI(); +} + +void LoginModule::reset() +{ + init(); +} + +void LoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void LoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void LoginModule::initUI() +{ + if (m_loginWidget) { + return; + } + m_loginWidget = new QWidget; + m_loginWidget->setAccessibleName(QStringLiteral("LoginWidget")); + m_loginWidget->setMinimumSize(260, 100); + + m_loginWidget->setLayout(new QHBoxLayout); + QPushButton *passButton = new QPushButton("Validation passed", m_loginWidget); + passButton->setFixedSize(160, 40); + m_loginWidget->layout()->addWidget(passButton); + + connect(passButton, &QPushButton::clicked, this, [this] { + AuthCallbackData data; + data.account = "uos"; // 需要与当前的用户名匹配 + data.token = "1"; + data.result = AuthResult::Success; + m_authCallback(&data, m_appData); + }, Qt::DirectConnection); +} + +} // namespace module +} // namespace dss +``` + +### 元数据文件 + +插件需要提供一个 JSON 格式的元数据文件,用于描述插件的基本信息和兼容性要求。 + +**文件名:** `login.json` + +**基本格式:** +```json +{ + "api": "2.0.0", + "pluginType": "Login" +} +``` + +### 二进制路径 + +登录器会在启动时从 `/usr/lib/dde-session-shell/modules` 目录下加载后缀为 `.so` 的插件。在开发时需要在 `CMakeLists.txt` 或 `.pro` 文件中设置插件的安装路径为 `/usr/lib/dde-session-shell/modules`。 + +# 安全性 + +在整个流程中,登录器不参与用户身份的校验,用户身份的真实性和访问权限完全由认证插件来保证。因此,在开发认证插件时对于安全性的考虑要全面且慎重。这是除了功能需求之外最重要的特性,下面列出一些常见的安全考量: + +- 输入密码等认证信息必须使用加密手段防止数据被窃取和中间人攻击。 +- 图形界面程序不应该将自己提权到 root 权限(含 capabilities)运行。 +- 存储的用户数据(如密码与隐私数据)必须进行高强度加密保护。 +- 未经用户明确授权,不得保存或传输用户数据。 + +# 可靠性 + +登录器会将插件加载到内存中。如果认证插件的质量不过关,出现指针错误、内存溢出、在 UI 线程做耗时操作等问题,可能导致登录器崩溃或卡死,进而导致用户无法正常进入系统。由于登录器是系统的门户,如果用户无法正常使用登录器就无法进入系统,这是一个致命性问题。因此,在开发时必须将可靠性作为重点考虑因素。 + +### API 版本兼容性 + +认证插件的工程需要增加一个 json 文件,用来描述当前插件适配的 api 版本,在代码中使用 Q_PLUGIN_METADATA 将 json 文件设置为 metadata 文件,例如:Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Login" FILE "login.json")。登录器在加载插件时会解析 JSON 文件中的内容,获取 API 版本号。 +登录器会做到小版本向下兼容(1.x.x 版本都互相兼容),如果出现无法兼容的情况(比如增加了接口头文件的虚函数,导致二进制不兼容),此时会修改大版本号(比如从 1.x.x 变更到 2.x.x)。登录器会比对 API 版本号,如果低于可兼容的版本号,则不会加载插件,以保证登录器本身能够正常运行。JSON 文件示例: + +```c++ +{ + "api": "2.0.0", + "pluginType": "Login" +} +``` + +login_module_interface.h 中 API_VERSION 宏定义的字符串即为当前 API 的版本号,JSON 文件中 api 字段记录的版本号务必与 API_VERSION 保持一致。 diff --git a/files/50-deepin.conf b/files/50-deepin.conf new file mode 100644 index 00000000..e47872eb --- /dev/null +++ b/files/50-deepin.conf @@ -0,0 +1,10 @@ +[LightDM] +minimum-vt=1 + +[Seat:*] +xserver-command=X -background none +greeter-session=lightdm-deepin-greeter +user-session=deepin +pam-autologin-service=deepin-lightdm-autologin +# in case ~/.Xauthority changed to root owned. +session-cleanup-script=/usr/sbin/deepin-fix-xauthority-perm diff --git a/files/dde-lock-loader-wrapper b/files/dde-lock-loader-wrapper new file mode 100644 index 00000000..e067c447 --- /dev/null +++ b/files/dde-lock-loader-wrapper @@ -0,0 +1,29 @@ +#!/bin/bash +# dde-lock wrapper for deepin-security-loader +# Launches dde-lock through security loader to get authorization +# for calling protected system services without polkit popup. + +REAL_BINARY="/usr/libexec/deepin/dde-lock" +LOADER="/usr/bin/deepin-security-loader" +LOADER_EXEC="/usr/bin/deepin-security-loader-exec" + +# Log to systemd journal with tag "dde-lock" +log_to_journal() { + logger -t dde-lock -p user.info "$1" +} + +# Log startup +log_to_journal "dde-lock launched with args: $*" + +# Check if loader is available and has proper capabilities +if [ -x "$LOADER" ] && [ -x "$LOADER_EXEC" ]; then + if getcap "$LOADER_EXEC" 2>/dev/null | grep -q cap_setgid; then + # Launch via loader with authorization groups + log_to_journal "Using deepin-security-loader with authorization groups" + exec "$LOADER" --group deepin-daemon -- "$REAL_BINARY" "$@" + fi +fi + +# Fallback: direct launch without loader (no polkit-free authorization) +log_to_journal "Fallback: launching directly without security loader" +exec "$REAL_BINARY" "$@" diff --git a/files/dde-lock.desktop b/files/dde-lock.desktop index 20a9226c..4108561e 100644 --- a/files/dde-lock.desktop +++ b/files/dde-lock.desktop @@ -8,3 +8,10 @@ OnlyShowIn=Deepin Type=Application X-Deepin-Vendor=user-custom X-Deepin-TurboType=dtkwidget + +Name[en_US]=Lock screen +Name[zh_CN]=锁屏 +Name[zh_TW]=鎖定螢幕 +Name[zh_HK]=鎖定螢幕 +Name[ug]=ئېكران قۇلۇپى +Name[bo]=བརྙན་ཡོལ་སྒོ་ལྕགས་རྒྱག་པ། \ No newline at end of file diff --git a/files/deepin-debug-config/org.deepin.dde.session-shell.json b/files/deepin-debug-config/org.deepin.dde.session-shell.json new file mode 100644 index 00000000..729ea3cf --- /dev/null +++ b/files/deepin-debug-config/org.deepin.dde.session-shell.json @@ -0,0 +1,11 @@ +{ + "name": "dde-session-shell", + "group": "dde", + "submodules": [ + { + "name": "org.deepin.dde.lock", + "exec": "org.deepin.dde.lock.sh" + } + ], + "version": "V1.0" +} diff --git a/files/deepin-greeter b/files/deepin-greeter index ed9b6f77..6eaad100 100755 --- a/files/deepin-greeter +++ b/files/deepin-greeter @@ -1,5 +1,10 @@ #!/bin/bash -for i in /etc/deepin/greeters.d/*; do - $i -done \ No newline at end of file +dde-dconfig --get -a org.deepin.dde.lightdm-deepin-greeter -r org.deepin.dde.lightdm-deepin-greeter -k defaultGreeterSession | grep "wayland" +if [ $? -eq 0 ];then + /usr/share/dde-session-shell/greeters.d/wayland/launch-kwin-wayland +else + for i in /usr/share/dde-session-shell/greeters.d/x/*; do + $i + done +fi diff --git a/files/deepin-log-config/org.deepin.dde.session-shell.json b/files/deepin-log-config/org.deepin.dde.session-shell.json new file mode 100644 index 00000000..16561bc6 --- /dev/null +++ b/files/deepin-log-config/org.deepin.dde.session-shell.json @@ -0,0 +1,20 @@ +{ + "name": "dde-lock", + "group": "dde", + "submodules": [ + { + "name": "session-shell.shell", + "filter": "org.deepin.dde.shell", + "exec": "/usr/bin/dde-lock", + "logType": "journal" + }, + { + "name": "session-shell.active", + "filter": "dss.active", + "exec": "/usr/bin/dde-lock", + "logType": "journal" + } + ], + "visible": 1, + "version": "V1.0" +} diff --git a/files/launch-binary b/files/launch-binary new file mode 100755 index 00000000..c5378768 --- /dev/null +++ b/files/launch-binary @@ -0,0 +1,52 @@ +#!/bin/bash + +# 设置QT缩放相关的环境变量 +greeter_display_setting_path="/usr/bin/greeter-display-setting" +if [ -f $greeter_display_setting_path ]; then + scale_env=$(/usr/bin/greeter-display-setting | tail -1) + export $scale_env +else + echo "$greeter_display_setting_path does not exist, can't do scale" +fi + +# 判断是否有脚本需要在greeter之前调用 +pre_greeter_out=$(/usr/share/dde-session-shell/greeters.d/pre-greeter) +exit_code=$? +exec_path=$(printf "%b\n" "$pre_greeter_out" | tail -1) + +if [[ $exit_code == 0 ]]; then + echo "Pre-greeter path is: "$exec_path + $exec_path +else + echo "There is nothing to do before start greeter" +fi + +# 启动greeter +# greeter没正常退出的情况下,会重新拉起greeter +start_lightdm_deepin_greeter() { + echo "-lightdm-deepin-greeter starting..." 1>&2 + while true; do + /usr/bin/lightdm-deepin-greeter + exit_status=$? + # 143 为收到kill信号后退出码 + if [ $exit_status -eq 0 ] || [ $exit_status -eq 143 ]; then + echo "-lightdm-deepin-greeter exit code: $exit_status" 1>&2 + break + else + current_time=$(date '+%Y-%m-%d %H:%M:%S') + echo "$current_time: -lightdm-deepin-greeter exited with non-zero status. Restarting..." 1>&2 + fi + done +} + +dde-dconfig --get -a org.deepin.dde.lightdm-deepin-greeter -r org.deepin.dde.lightdm-deepin-greeter -k enableLighterGreeter | grep "true" +if [ $? -eq 0 ];then + /usr/bin/lightdm-deepin-greeter-lighter + + # 没正常退出的情况下,仍然拉起原版Greeter + if [ $? -ne 0 ];then + start_lightdm_deepin_greeter + fi +else + start_lightdm_deepin_greeter +fi diff --git a/files/pam.d/dde-lock b/files/pam.d/dde-lock new file mode 100644 index 00000000..b404e340 --- /dev/null +++ b/files/pam.d/dde-lock @@ -0,0 +1,4 @@ +#%PAM-1.0 +auth include common-auth +account include common-auth +session include common-auth diff --git a/files/pam.d/deepin-lightdm-autologin b/files/pam.d/deepin-lightdm-autologin new file mode 100644 index 00000000..2edcbe79 --- /dev/null +++ b/files/pam.d/deepin-lightdm-autologin @@ -0,0 +1,2 @@ +auth requisite pam_inhibit_autologin.so +@include lightdm-autologin \ No newline at end of file diff --git a/files/permission-interfaces/auth.json b/files/permission-interfaces/auth.json new file mode 100644 index 00000000..77f114f1 --- /dev/null +++ b/files/permission-interfaces/auth.json @@ -0,0 +1,14 @@ +{ + "DestList": [ + { + "DbusName": "org.deepin.dde.Lastore1", + "DbusPath": "/org/deepin/dde/Lastore1", + "DbusInterface": "org.deepin.dde.Lastore1.Manager" + }, + { + "DbusName": "org.deepin.dde.Authenticate1", + "DbusPath": "/org/deepin/dde/Authenticate1", + "DbusInterface": "org.deepin.dde.Authenticate1" + } + ] +} diff --git a/files/pre-greeter b/files/pre-greeter new file mode 100755 index 00000000..516533d4 --- /dev/null +++ b/files/pre-greeter @@ -0,0 +1,24 @@ +#!/bin/bash + +folder_path="/usr/share/dde-session-shell/greeters.d/launch.conf.d" + +if [ -d ${folder_path} ]; then + # 遍历文件夹中的所有文件 + for file in $(ls -1 "$folder_path"/*.json | sort -r -n); do + if [[ -f "$file" ]]; then + need_exec_script=$(jq -r '.NeedExecScript' "$file") + if [[ ! -z "$need_exec_script" ]]; then + # 执行需要执行的脚本 + "$need_exec_script" + exit_code=$? + if [[ $exit_code -eq 0 ]]; then + exec_path=$(jq -r '.ExecPath' "$file") + echo "$exec_path" + exit 0 + fi + fi + fi + done +fi + +exit 1 diff --git a/files/snipe/dde-lock.desktop b/files/snipe/dde-lock.desktop new file mode 100644 index 00000000..f6cac095 --- /dev/null +++ b/files/snipe/dde-lock.desktop @@ -0,0 +1,17 @@ +[Desktop Entry] +Name=Deepin Lock +Comment=Deepin Lock +Encoding=UTF-8 +Exec=/usr/bin/dde-lock +NoDisplay=true +OnlyShowIn=DDE +Type=Application +X-Deepin-Vendor=user-custom +X-Deepin-TurboType=dtkwidget + +Name[en_US]=Lock screen +Name[zh_CN]=锁屏 +Name[zh_TW]=鎖定螢幕 +Name[zh_HK]=鎖定螢幕 +Name[ug]=ئېكران قۇلۇپى +Name[bo]=བརྙན་ཡོལ་སྒོ་ལྕགས་རྒྱག་པ། diff --git a/files/snipe/deepin-greeter b/files/snipe/deepin-greeter new file mode 100755 index 00000000..ed9b6f77 --- /dev/null +++ b/files/snipe/deepin-greeter @@ -0,0 +1,5 @@ +#!/bin/bash + +for i in /etc/deepin/greeters.d/*; do + $i +done \ No newline at end of file diff --git a/files/snipe/org.deepin.dde.LockFront1.service b/files/snipe/org.deepin.dde.LockFront1.service new file mode 100644 index 00000000..16fa694d --- /dev/null +++ b/files/snipe/org.deepin.dde.LockFront1.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.deepin.dde.LockFront1 +SystemdService=dde-lock.service +Exec=/usr/bin/dde-lock diff --git a/files/snipe/org.deepin.dde.ShutdownFront1.service b/files/snipe/org.deepin.dde.ShutdownFront1.service new file mode 100644 index 00000000..bd57993a --- /dev/null +++ b/files/snipe/org.deepin.dde.ShutdownFront1.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.deepin.dde.ShutdownFront1 +SystemdService=dde-lock.service +Exec=/usr/bin/dbus-send --print-reply --session --dest=org.deepin.dde.Application1.Manager /org/deepin/dde/Application1/Manager org.deepin.dde.Application1.Manager.LaunchApp string:/usr/share/applications/dde-lock.desktop uint32:0 array:string:--daemon diff --git a/scripts/00-xrandr b/files/snipe/scripts/00-xrandr similarity index 100% rename from scripts/00-xrandr rename to files/snipe/scripts/00-xrandr diff --git a/scripts/10-cursor-theme b/files/snipe/scripts/10-cursor-theme similarity index 100% rename from scripts/10-cursor-theme rename to files/snipe/scripts/10-cursor-theme diff --git a/files/snipe/scripts/lightdm-deepin-greeter b/files/snipe/scripts/lightdm-deepin-greeter new file mode 100755 index 00000000..721be88b --- /dev/null +++ b/files/snipe/scripts/lightdm-deepin-greeter @@ -0,0 +1,30 @@ +#!/bin/bash +display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon" +if [ -x $display_daemon ]; then + $display_daemon & +fi +xsettingsd_conf="/etc/lightdm/deepin/xsettingsd.conf" +if [ -e $xsettingsd_conf ]; then + xsettingsd -c $xsettingsd_conf & +else + # xsettingsd.conf 不存在时,通过 greeter-display-setting 设置 QT 缩放环境变量 + greeter_display_setting_path="/usr/bin/greeter-display-setting" + if [ -f $greeter_display_setting_path ]; then + scale_env=$(/usr/bin/greeter-display-setting | tail -1) + export $scale_env + fi +fi + +# 判断是否有脚本需要在greeter之前调用。与更新相关功能 +pre_greeter_out=$(/usr/share/dde-session-shell/greeters.d/pre-greeter) +exit_code=$? +exec_path=$(printf "%b\n" "$pre_greeter_out" | tail -1) + +if [[ $exit_code == 0 ]]; then + echo "Pre-greeter path is: "$exec_path + $exec_path +else + echo "There is nothing to do before start greeter" +fi + +/usr/bin/lightdm-deepin-greeter diff --git a/files/wayland/kwin_wayland_helper-wayland b/files/wayland/kwin_wayland_helper-wayland deleted file mode 100755 index c0287c0c..00000000 --- a/files/wayland/kwin_wayland_helper-wayland +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -export KWIN_COMPOSE=O2ES -export GDK_BACKEND=x11 -export KWIN_USE_BUFFER_AGE=1 - -if [ ! -f "$HOME/.config/kglobalshortcutsrc" ]; then - cp -n /etc/xdg/kglobalshortcutsrc $HOME/.config/kglobalshortcutsrc -fi - -export QT_LOGGING_RULES="kwin*=true;kwin_libinput=false;" -export QT_WAYLAND_FORCE_DPI=$(expr `gsettings get com.deepin.xsettings xft-dpi` / 1024) -export QT_MESSAGE_PATTERN="[%{time yyyy-MM-dd hh:mm:ss.zzz}] %{function}:%{line} - %{message}" - -if [ -f "$HOME/.config/locale.conf" ]; then - source $HOME/.config/locale.conf -fi - -#崩溃后重新登录会冲掉崩溃时候的kwin日志,此处加入一次拷贝,保证可以获取到kwin崩溃时候的那次日志 -cp $HOME/.kwin.log $HOME/.kwin-old.log -exec /usr/bin/kwin_wayland -platform dde-kwin-wayland --xwayland --drm --no-lockscreen startdde-wayland 1> $HOME/.kwin.log 2>&1 diff --git a/files/wayland/deepin-greeter-wayland b/files/wayland/launch-kwin-wayland similarity index 53% rename from files/wayland/deepin-greeter-wayland rename to files/wayland/launch-kwin-wayland index 0a07aba9..452ca508 100755 --- a/files/wayland/deepin-greeter-wayland +++ b/files/wayland/launch-kwin-wayland @@ -6,5 +6,6 @@ export XDG_DATA_DIRS=/usr/share export GDK_BACKEND=x11 export QT_QPA_PLATFORM=wayland export KWIN_COMPOSE=O2ES +export QT_WAYLAND_SHELL_INTEGRATION=kwayland-shell -/usr/bin/kwin_wayland --drm --no-lockscreen /etc/deepin/greeters.d/lightdm-deepin-greeter +/usr/bin/kwin_wayland --xwayland --drm --no-lockscreen /usr/share/dde-session-shell/greeters.d/wayland/lightdm-deepin-greeter-wayland diff --git a/files/wayland/lightdm-deepin-greeter-default-wayland.json b/files/wayland/lightdm-deepin-greeter-default-wayland.json deleted file mode 100755 index 8e29c9cf..00000000 --- a/files/wayland/lightdm-deepin-greeter-default-wayland.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "magic": "dsg.config.meta", - "version": "1.0", - "contents": { - "useSolidBackground": { - "value": false, - "serial": 0, - "flags": ["global"], - "name": "UseSolidBackground", - "name[zh_CN]": "使用纯色背景", - "description": "是否使用纯色背景,默认为否。开启配置时,那么将不会加载背景图片,降低内存占用。禁用设置时,加载背景图片,比较美观,但是会增加内存占用。", - "permissions": "readwrite", - "visibility": "private" - }, - "allowSwitchingToWayland": { - "value": false, - "serial": 0, - "flags": ["global"], - "name": "AllowSwitchingToWayland", - "name[zh_CN]": "允许用户切换到wayland", - "description": "是否允许用户切换到wayland,默认为否。开启配置时,如果用户安装了wayland和其它桌面环境,登录界面会显示桌面环境切换按钮,点击后用户可以选择wayland桌面环境。关闭配置时,就算用户安装了wayland环境,也会默认隐藏起来,不让用户切换到wayland环境", - "permissions": "readwrite", - "visibility": "private" - }, - "defaultSession": { - "value": "Wayland", - "serial": 0, - "flags": ["global"], - "name": "DefaultSessionName", - "name[zh_CN]": "默认桌面环境名称", - "description": "默认的桌面环境名称,默认为deepin。新建用户首次登录的时候,默认的桌面由此配置决定", - "permissions": "readwrite", - "visibility": "private" - }, - "numLockState": { - "value": [], - "serial": 0, - "flags": ["global"], - "name": "NumLockState", - "name[zh_CN]": "数字键盘状态", - "description": "用户的小键盘状态,True为打开,False为关闭,与用户绑定,格式为:\"用户名:状态\",例如\"uos:True\"。当用户改变状态时会记录下来,切换用户时会跟随用户改变。", - "permissions": "readwrite", - "visibility": "private" - }, - "hideOnboard":{ - "value": false, - "serial": 0, - "flags": ["global"], - "name": "HideOnboard", - "name[zh_CN]": "隐藏屏幕键盘", - "description": "登录界面隐藏屏幕键盘;false:不隐藏,true:隐藏。默认值为false;", - "permissions": "readwrite", - "visibility": "private" - } - } -} \ No newline at end of file diff --git a/files/wayland/lightdm-deepin-greeter-wayland b/files/wayland/lightdm-deepin-greeter-wayland index 03822439..98f4caae 100755 --- a/files/wayland/lightdm-deepin-greeter-wayland +++ b/files/wayland/lightdm-deepin-greeter-wayland @@ -1,9 +1,4 @@ #!/bin/bash -display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon" -if [ -x $display_daemon ]; then - $display_daemon & -fi - export QT_QPA_PLATFORM=wayland export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/plugins/platforms export QT_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/qt5/plugins @@ -12,4 +7,45 @@ export XDG_DATA_DIRS=/usr/share export XDG_CURRENT_DESKTOP=Deepin export QT_DEBUG_PLUGINS=1 -/usr/bin/lightdm-deepin-greeter +display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon" +dde_wloutput_daemon="/usr/bin/dde-wloutput-daemon" +if [ -x $display_daemon ]; then + $dde_wloutput_daemon & + $display_daemon 1>/tmp/greeter-display-daemon.log 2>&1 & +fi + + +#在满足条件下,设置tapToClick=true +#解析dbus信息输出 +dbus_values_get_strings(){ + local input="$1" + echo "$input" | grep -oP 'string \K".*?"' | tr -d '"' +} +dbus_values_get_bool(){ + local input="$1" + echo "$input" | grep -oP 'boolean \Ktrue|false' | awk '{print $1}' +} + +#判断并设置设备属性 +device_handle(){ + local input="$1" + local dbus_touchpad=$(dbus-send --session --print-reply --dest=org.kde.KWin $input org.freedesktop.DBus.Properties.Get string:"org.kde.KWin.InputDevice" string:"touchpad") + local touchpad=$(dbus_values_get_bool "$dbus_touchpad") + + if [ "$touchpad" = "true" ]; then + dbus-send --session --print-reply --dest=org.kde.KWin "$input" org.freedesktop.DBus.Properties.Set string:"org.kde.KWin.InputDevice" string:"tapToClick" variant:boolean:true + fi +} + +#获取设备列表 +dbus_devices=$(dbus-send --session --print-reply --dest=org.kde.KWin /org/kde/KWin/InputDevice org.freedesktop.DBus.Properties.Get string:"org.kde.KWin.InputDeviceManager" string:"devicesSysNames") +devices_strings=$(dbus_values_get_strings "$dbus_devices") + +#遍历设备列表 +device_path="/org/kde/KWin/InputDevice/" +for dev in $devices_strings; do + path="${device_path}${dev}" + device_handle "$path" +done + +/usr/share/dde-session-shell/greeters.d/launch-binary diff --git a/files/x/00-xrandr b/files/x/00-xrandr new file mode 100755 index 00000000..c341de0f --- /dev/null +++ b/files/x/00-xrandr @@ -0,0 +1,25 @@ +#!/bin/bash +# +# xrandr 输出的主屏幕有可能是断开的 +# $ xrandr|egrep -o '^.* (connected|primary)' +# DVI-I-0 disconnected primary +# DVI-I-1 connected +# VGA-1-1 connected + +xinfo(){ + local IFS=$'\n' + XINFO=($(xrandr|egrep -o '^.* connected( primary)?')) +} + +# 仅当连接两个屏幕时进行如下操作 +if xinfo && ((${#XINFO[@]} == 2)); then + # 假设第一行为主屏 + primary=(${XINFO[0]}) + second=(${XINFO[1]}) + # 如果第二行输出含有 primary, 则交换 + if ((${#second[@]} == 3)); then + primary=(${XINFO[1]}) + second=(${XINFO[0]}) + fi + xrandr --output ${second[0]} --right-of ${primary[0]} --auto +fi diff --git a/files/x/10-cursor-theme b/files/x/10-cursor-theme new file mode 100755 index 00000000..82d98f5f --- /dev/null +++ b/files/x/10-cursor-theme @@ -0,0 +1,3 @@ +#!/bin/bash + +[[ $(xrdb -query) == *'Xcursor.theme:'* ]] || xrdb -merge <<< 'Xcursor.theme: bloom' diff --git a/files/x/lightdm-deepin-greeter b/files/x/lightdm-deepin-greeter new file mode 100755 index 00000000..732ed230 --- /dev/null +++ b/files/x/lightdm-deepin-greeter @@ -0,0 +1,19 @@ +#!/bin/bash + +xsettingsd_conf="/etc/lightdm/deepin/xsettingsd.conf" +if [ -e $xsettingsd_conf ]; then + xsettingsd -c $xsettingsd_conf & +else + # 设置为推荐分辨率 + outputs=$(xrandr --query | grep " connected" | cut -d" " -f1) + for output in $outputs; do + xrandr --output $output --preferred + done +fi + +display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon" +if [ -x $display_daemon ]; then + $display_daemon 1>/tmp/greeter-display-daemon.log 2>&1 & +fi + +/usr/share/dde-session-shell/greeters.d/launch-binary diff --git a/files/lightdm-deepin-greeter.desktop b/files/x/lightdm-deepin-greeter.desktop similarity index 100% rename from files/lightdm-deepin-greeter.desktop rename to files/x/lightdm-deepin-greeter.desktop diff --git a/interface/base_module_interface.h b/interface/base_module_interface.h index b12ac330..56f8be22 100644 --- a/interface/base_module_interface.h +++ b/interface/base_module_interface.h @@ -1,32 +1,32 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef MODULE_INTERFACE_H #define MODULE_INTERFACE_H #include +const QString BASE_API_VERSION = "2.0.0"; + namespace dss { namespace module { +/** + * @brief 消息回调函数 + * @param const QString & 发送给登录器的数据 + * @param void * 登录器回传指针 + * + * @return 登录器返回的数据 + * @since 2.0.0 + * + * 传入和传出的数据都是json格式的字符串,详见登录插件接口说明文档 + * + */ +using MessageCallbackFunc = QString (*)(const QString&, void *); + +using AppDataPtr = void*; + class BaseModuleInterface { public: @@ -35,8 +35,20 @@ class BaseModuleInterface * 模块的类型 */ enum ModuleType { - LoginType, - TrayType + LoginType, // 登陆插件 + TrayType, // 托盘插件 + FullManagedLoginType, // 全托管插件 + IpcAssistLoginType, // 用于接收厂商密码插件 + PasswordExtendLoginType, // 密码认证扩展插件,需要两个都认证通过后 + }; + + /** + * @brief The LoadType enum + * 模块加载的类型 + */ + enum LoadType { + Load, // 加载插件 + Notload // 不加载插件 }; virtual ~BaseModuleInterface() = default; @@ -44,12 +56,16 @@ class BaseModuleInterface /** * @brief 界面相关的初始化 * 插件在非主线程加载,故界面相关的初始化需要放在这个方法里,由主程序调用并初始化 + * + * @since 1.0.0 */ virtual void init() = 0; /** * @brief 键值,用于与其它模块区分 - * @return QString + * @return QString 插件的唯一标识,由插件自己定义 + * + * @since 1.0.0 */ virtual QString key() const = 0; @@ -57,14 +73,32 @@ class BaseModuleInterface * @brief 模块想显示的界面 * content 对象由模块自己管理 * @return QWidget* + * + * @since 1.0.0 */ virtual QWidget *content() = 0; /** - * @brief 模块的类型 - * @return ModuleType + * @brief 模块的类型 登陆器会根据不同 + * @return ModuleType 详见`ModuleType`说明 + * + * @since 1.0.0 */ virtual ModuleType type() const = 0; + + /** + * @brief 模块加载类型 + * + * 登陆器在加载插件的时候会调用这个接口,如果返回Load,那么登陆会加载插件,返回其它则不会加载插件。 + * 非全平台或全架构的插件需要重新实现这个接口,根据实际情况处理。 + * + * @return LoadType 详见`LoadType`说明 + * + * @since 1.1.0 + */ + virtual LoadType loadPluginType() const { return Load; } + + // Warning: 不要增加虚函数,即使在最后面(会改变派生类的虚表) }; } // namespace module diff --git a/interface/login_module_interface.h b/interface/login_module_interface.h index c40ae254..90eff7cb 100644 --- a/interface/login_module_interface.h +++ b/interface/login_module_interface.h @@ -1,56 +1,137 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGINMODULEINTERFACE_H #define LOGINMODULEINTERFACE_H #include "base_module_interface.h" +/** +* 这个接口已经过时,请使用login_module_interface_v2.h中的2.x.x版本 +*/ + namespace dss { namespace module { +const QString LOGIN_API_VERSION = "1.2.0"; + +enum AuthResult { + None = 0, + Success, + Failure +}; + +enum CustomLoginType { + CLT_Default = 0, // 默认登录 + CLT_MFA, // 多因子 + CLT_ThirdParty, // 第三方 +}; + /** * @brief 认证插件需要传回的数据 */ -struct AuthCallbackData{ - int result; // 认证结果 +struct AuthCallbackData { + int result = AuthResult::None; // 认证结果 std::string account; // 账户 - std::string token; // 令牌 + std::string token; // 令牌 std::string message; // 提示消息 - std::string json; // 预留数据 + std::string json; // 预留数据 +}; + +/** + * @brief The AppType enum + * 发起认证的应用类型 + */ +enum AppType { + TypeNone = 0, // 其他 + Login = 1, // 登录 + Lock = 2 // 锁屏 +}; + +/** + * @brief + */ +enum DefaultAuthLevel { + NoDefault = 0, // 如果获取到上次认证成功的类型,则默认使用上次登陆成功的类型,否则根据系统默认的顺序来选择 + + //Deprecated,不再处理这个类型,没有实际的使用价值 + Default, // 如果获取到上次认证成功的类型,则默认使用上次登陆成功的类型,否则使用插件认证 + + StrongDefault // 无论是否可以获取到上次认证成功的类型,都默认选择插件验证 +}; + +/** + * @brief The AuthType enum + * 认证类型 + */ +enum AuthType { + AT_None = 0, // none + AT_Password = 1 << 0, // 密码 + AT_Fingerprint = 1 << 1, // 指纹 + AT_Face = 1 << 2, // 人脸 + AT_ActiveDirectory = 1 << 3, // AD域 + AT_Ukey = 1 << 4, // ukey + AT_FingerVein = 1 << 5, // 指静脉 + AT_Iris = 1 << 6, // 虹膜 + AT_Passkey = 1 << 7, // 安全密钥 + AT_Pattern = 1 << 8, // 手势 + AT_PAM = 1 << 29, // PAM + AT_Custom = 1 << 30, // 自定义 + AT_All = -1 // all +}; + +/** + * @brief The AuthStatus enum + * 认证状态 + */ +enum AuthState { + AS_None = -1, // none + AS_Success, // 成功,此次认证的最终结果 + AS_Failure, // 失败,此次认证的最终结果 + AS_Cancel, // 取消,当认证没有给出最终结果时,调用 End 会出发 Cancel 信号 + AS_Timeout, // 超时 + AS_Error, // 错误 + AS_Verify, // 验证中 + AS_Exception, // 设备异常,当前认证会被 End + AS_Prompt, // 设备提示 + AS_Started, // 认证已启动,调用 Start 之后,每种成功开启都会发送此信号 + AS_Ended, // 认证已结束,调用 End 之后,每种成功关闭的都会发送此信号,当某种认证类型被锁定时,也会触发此信号 + AS_Locked, // 认证已锁定,当认证类型锁定时,触发此信号。该信号不会给出锁定等待时间信息 + AS_Recover, // 设备恢复,需要调用 Start 重新开启认证,对应 AS_Exception + AS_Unlocked, // 认证解锁,对应 AS_Locked + AS_Unknown, // 未知状态 + AS_VerifyCode, // 需要验证码 }; /** - * @brief 回调函数 - * AuthData: 需要传回的数据 + * @brief 验证回调函数 + * @param const AuthCallbackData * 需要传回的验证数据 + * @param void * 登录器回传指针 * void *: ContainerPtr */ using AuthCallbackFun = void (*)(const AuthCallbackData *, void *); +/** + * @brief 验证回调函数 + * @param const std::string & 发送给登录器的数据 + * @param void * 登录器回传指针 + * + * @return 登录器返回的数据 + * @since 1.2.0 + * + * 传入和传出的数据都是json格式的字符串,详见登录插件接口说明文档 + * + */ +using MessageCallbackFun = std::string (*)(const std::string &, void *); + /** * @brief 插件回调相关 */ -struct AuthCallback { - void *app_data; // 插件无需关注 - AuthCallbackFun callbackFun; // 回调函数 +struct LoginCallBack { + void *app_data; // 插件无需关注 + AuthCallbackFun authCallbackFun; + MessageCallbackFun messageCallbackFunc; }; class LoginModuleInterface : public BaseModuleInterface @@ -63,17 +144,43 @@ class LoginModuleInterface : public BaseModuleInterface ModuleType type() const override { return LoginType; } /** - * @brief 模块图标的路径 - * @return std::string + * @brief 模块加载的类型 + * @return LoadType + */ + LoadType loadPluginType() const override { return Load; } + + /** + * @brief 插件图标 + * @return 图标的绝对路径或者图标的名称(能够通过QIcon::fromTheme获取) + */ + virtual std::string icon() const { return ""; } + + /** + * @brief 设置回调函数 CallbackFun */ - virtual std::string icon() const { return nullptr; } + virtual void setCallback(LoginCallBack *) = 0; /** - * @brief 认证完成后,需要调用回调函数 CallbackFun + * @brief 登录器通过此函数发送消息给插件,获取插件的状态或者信息,使用json格式字符串in&out数据,方便后期扩展和定制。 + * + * @since 1.2.0 */ - virtual void setAuthFinishedCallback(AuthCallback *) = 0; + virtual std::string onMessage(const std::string &) { return "{}"; }; + + /** + * @brief 重置插件 + */ + virtual void reset() = 0; + + // Warning: 不要增加虚函数,即使在最后面(如果派生类也有虚函数,那么虚表寻址也会错误) }; +#ifndef ENABLE_DSS_SNIPE +typedef Q_DECL_DEPRECATED LoginModuleInterface LoginModuleInterfaceV2; +#else +Q_DECL_DEPRECATED typedef LoginModuleInterface LoginModuleInterfaceV2; +#endif + } // namespace module } // namespace dss diff --git a/interface/login_module_interface_v2.h b/interface/login_module_interface_v2.h new file mode 100644 index 00000000..7c9ccf3f --- /dev/null +++ b/interface/login_module_interface_v2.h @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGINMODULEINTERFACE_V2_H +#define LOGINMODULEINTERFACE_V2_H + +#include "base_module_interface.h" +#include "login_module_interface.h" + +namespace dss { +namespace module_v2 { + +const QString LOGIN_API_VERSION = "2.0.0"; + +using AuthResult = dss::module::AuthResult; +using AppType = dss::module::AppType; +using AuthType = dss::module::AuthType; +using AuthState = dss::module::AuthState; +using DefaultAuthLevel = dss::module::DefaultAuthLevel; +using AppDataPtr = dss::module::AppDataPtr; +using MessageCallbackFunc = dss::module::MessageCallbackFunc; + +/** + * @brief 认证插件需要传回的数据 + */ +struct AuthCallbackData { + int result = AuthResult::None; // 认证结果 + QString account; // 账户 + QString token; // 令牌 + QString message; // 提示消息 + QString json; // 预留数据 +}; + +/** + * @brief 验证回调函数 + * @param const AuthCallbackData * 需要传回的验证数据 + * @param void * 登录器回传指针 + * void *: ContainerPtr + */ +using AuthCallbackFun = void (*)(const AuthCallbackData *, void *); + +/** + * @brief 验证对象类型 + * + */ +enum AuthObjectType { + LightDM, // light display manager 显示管理器 + DeepinAuthenticate // deepin authenticate service 深度认证框架 +}; + +class LoginModuleInterfaceV2 : public dss::module::BaseModuleInterface +{ +public: + /** + * @brief 模块的类型 + * @return ModuleType 见`ModuleType`说明 + */ + ModuleType type() const override { return LoginType; } + + /** + * @brief 插件图标 + * @return 图标的绝对路径或者图标的名称(能够通过QIcon::fromTheme获取) + */ + virtual QString icon() const { return ""; } + + /** + * @brief 设置回调验证回调函数,此函数会在init函数之前调用 + * + * @param AuthCallbackFunc 详见`AuthCallbackFunc`说明 + * + * @since 2.0.0 + */ + virtual void setAuthCallback(AuthCallbackFun) = 0; + + /** + * @brief 插件需要在这个方法中重置UI和验证状态 + * 调用时机:通常验证开始之前登录器会调用这个方法,但是不保证每次验证前都会调用。 + * + * @since 2.0.0 + */ + virtual void reset() = 0; + + /** + * @brief 设置消息回调函数回调函数 CallbackFun + */ + virtual void setMessageCallback(MessageCallbackFunc) {} + + /** + * @brief 设置登录器的回调指针,插件需要保存指针,在使用回调函数的时候回传给登录器 + * + * 如果要使用回调函数,则必须实现此函数。 + * 函数可能会被重复调用,插件只需要保证回传的时候是最后一次设置的即可。 + * + * @since 2.0.0 + */ + virtual void setAppData(AppDataPtr) {} + + /** + * @brief 登录器通过此函数发送消息给插件,获取插件的信息或者同步登录器等。 + * + * 使用json格式字符串传输数据,具体协议见技术文档。 + * + * @since 2.0.0 + */ + virtual QString message(const QString &) { return "{}"; } + + // Warning: 不要增加虚函数,即使在最后面(如果派生类也有虚函数,那么虚表寻址也会错误) +}; + +} // namespace module_v2 +} // namespace dss + +Q_DECLARE_INTERFACE(dss::module_v2::LoginModuleInterfaceV2, "com.deepin.dde.shell.Modules_v2.Login") + +#endif // LOGINMODULEINTERFACE_V2_H diff --git a/interface/tray_module_interface.h b/interface/tray_module_interface.h index a4da19c2..18a1a4be 100644 --- a/interface/tray_module_interface.h +++ b/interface/tray_module_interface.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef TRAYMODULEINTERFACE_H #define TRAYMODULEINTERFACE_H @@ -26,6 +9,8 @@ #include +const QString TRAY_API_VERSION = "1.1.0"; + namespace dss { namespace module { @@ -38,6 +23,16 @@ class TrayModuleInterface : public BaseModuleInterface */ ModuleType type() const override { return TrayType; } + /** + * @brief 模块加载的类型 + * @return LoadType + */ + LoadType loadPluginType() const override { return Load; } + + /** + * @brief 插件图标 + * @return 图标的绝对路径或者图标的名称(能够通过QIcon::fromTheme获取) + */ virtual QString icon() const = 0; /** @@ -67,6 +62,33 @@ class TrayModuleInterface : public BaseModuleInterface */ virtual void invokedMenuItem(const QString &menuId, const bool checked) const = 0; + /** + * @brief 设置消息回调函数回调函数 MessageCallbackFunc + * + * @since 2.0.0 + */ + virtual void setMessageCallback(MessageCallbackFunc) {} + + /** + * @brief 设置登录器的回调指针,插件需要保存指针,在使用回调函数的时候回传给登录器 + * + * 如果要使用回调函数,则必须实现此函数。 + * 函数可能会被重复调用,插件只需要保证回传的时候是最后一次设置的即可。 + * + * @since 2.0.0 + */ + virtual void setAppData(AppDataPtr) {} + + /** + * @brief 登录器通过此函数发送消息给插件,获取插件的信息或者同步登录器等。 + * + * 使用json格式字符串传输数据,具体协议见技术文档。 + * + * @since 2.0.0 + */ + virtual QString message(const QString &) { return "{}"; } + + // Warning: 不要增加虚函数,即使在最后面(如果派生类也有虚函数,那么虚表寻址也会错误) }; } // namespace module diff --git a/lighter-greeter/CMakeLists.txt b/lighter-greeter/CMakeLists.txt new file mode 100644 index 00000000..ee99c6df --- /dev/null +++ b/lighter-greeter/CMakeLists.txt @@ -0,0 +1,66 @@ +project(lightdm-deepin-greeter-lighter) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + +# Find the library +find_package(PkgConfig REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5DBus REQUIRED) +find_package(DtkWidget REQUIRED) + +# Find the library +find_package(PkgConfig REQUIRED) +pkg_check_modules(XCB_EWMH REQUIRED xcb-ewmh x11 xi xcursor xfixes xrandr xext xtst) +pkg_check_modules(Greeter REQUIRED liblightdm-qt5-3) +pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) +pkg_check_modules(QGSettings REQUIRED gsettings-qt) + +add_executable(${PROJECT_NAME} + "main.cpp" + "lighterbackground.h" + "lighterbackground.cpp" + "lightergreeter.h" + "lightergreeter.cpp" + "lighterscreenmanager.h" + "lighterscreenmanager.cpp" + "../src/widgets/abstractfullbackgroundinterface.h" + "../src/widgets/timewidget.h" + "../src/widgets/timewidget.cpp" + "../src/widgets/dlineeditex.h" + "../src/widgets/dlineeditex.cpp" + "../src/widgets/transparentbutton.h" + "../src/widgets/transparentbutton.cpp" + "../src/widgets/useravatar.h" + "../src/widgets/useravatar.cpp" + "../src/global_util/constants.h" + "../src/global_util/public_func.h" + "../src/global_util/public_func.cpp" + "../src/global_util/dconfig_helper.h" + "../src/global_util/dconfig_helper.cpp" + "../resources.qrc" + ) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${DtkWidget_INCLUDE_DIRS} + ${Greeter_INCLUDE_DIRS} + ${DFrameworkDBus_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ${XCB_EWMH_INCLUDE_DIRS} + ) + +target_link_libraries(${PROJECT_NAME} + ${Qt5Widgets_LIBRARIES} + ${Qt5DBus_LIBRARIES} + ${DtkWidget_LIBRARIES} + ${DtkCore_LIBRARIES} + ${Greeter_LIBRARIES} + ${DFrameworkDBus_LIBRARIES} + ${QGSettings_LIBRARIES} + ${XCB_EWMH_LIBRARIES} + ) + +install(TARGETS lightdm-deepin-greeter-lighter DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/lighter-greeter/lighterbackground.cpp b/lighter-greeter/lighterbackground.cpp new file mode 100644 index 00000000..b0c10991 --- /dev/null +++ b/lighter-greeter/lighterbackground.cpp @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include +#include +#include +#include +#include +#include +#include + +#include "lighterbackground.h" +#include "dconfig_helper.h" +#include "constants.h" + +LighterBackground::LighterBackground(QWidget *content, QWidget *parent) + : QWidget(parent) + , m_content(content) + , m_useSolidBackground(DConfigHelper::instance()->getConfig( "useSolidBackground", false).toBool()) + , m_showBlack(false) +{ + Q_ASSERT(m_content); + + this->installEventFilter(this); + +#ifndef QT_DEBUG + if (!qgetenv("XDG_SESSION_TYPE").startsWith("wayland")) { + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + } else { + setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Window); + + setAttribute(Qt::WA_NativeWindow); // 创建窗口 handle + create(); + // onScreenDisplay 低于override,高于tooltip,希望显示在锁屏上方的界面,均需要调整层级为onScreenDisplay或者override + windowHandle()->setProperty("_d_dwayland_window-type", "onScreenDisplay"); + } +#endif + +} + +void LighterBackground::setScreen(QPointer screen, bool isVisible) +{ + Q_UNUSED(isVisible); + + setGeometry(screen->geometry()); + show(); + + if (screen == qApp->primaryScreen() && !m_showBlack) { + activateWindow(); + + m_content->hide(); + m_content->setParent(this); + m_content->resize(this->size()); + m_content->show(); + } +} + +void LighterBackground::onAuthFinished() +{ + m_showBlack = true; + + // 强制刷新,从而显示黑色画面,否则在lightdm开启会话时可能不会立即显示黑色 + repaint(); +} + +void LighterBackground::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + + const QRect trueRect(QPoint(0, 0), QSize(size() * devicePixelRatioF())); + + // 绘制纯黑色画面,提升体验 + if (m_showBlack) { + painter.fillRect(trueRect, Qt::black); + return; + } + + if (!QFile("/usr/share/backgrounds/default_background.jpg").exists() || m_useSolidBackground) { + painter.fillRect(trueRect, QColor(DDESESSIONCC::SOLID_BACKGROUND_COLOR)); + } else { + // cache the pixmap + static QPixmap background = QPixmap("/usr/share/backgrounds/default_background.jpg").scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + // 缓存图片大小和当前屏幕大小不一致时,需要调整尺寸 + if (background.size() != this->size()) { + background.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + + painter.drawPixmap(trueRect, background, QRect(trueRect.topLeft(), trueRect.size() * background.devicePixelRatioF())); + } +} + +bool LighterBackground::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == this && !m_showBlack + && (event->type() == QEvent::Enter)) { + activateWindow(); + + m_content->hide(); + m_content->setParent(this); + m_content->resize(this->size()); + m_content->show(); + } + + if (watched == this && !m_showBlack + && event->type() == QEvent::Resize) { + auto screen = qApp->screenAt(m_content->geometry().center()); + if (screen) { + m_content->resize(this->size()); + } + } + + return QWidget::eventFilter(watched, event); +} diff --git a/lighter-greeter/lighterbackground.h b/lighter-greeter/lighterbackground.h new file mode 100644 index 00000000..e50c6823 --- /dev/null +++ b/lighter-greeter/lighterbackground.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef LIGHTERBACKGROUND_H +#define LIGHTERBACKGROUND_H + +#include + +#include "abstractfullbackgroundinterface.h" + +class QPaintEvent; +class QScreen; + +class LighterBackground : public QWidget, public AbstractFullBackgroundInterface +{ + Q_OBJECT +public: + explicit LighterBackground(QWidget *content, QWidget *parent = nullptr); + + void setScreen(QPointer screen, bool isVisible = true) override; + +public Q_SLOTS: + void onAuthFinished(); + +protected: + void paintEvent(QPaintEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QWidget *m_content; + + bool m_useSolidBackground; + bool m_showBlack; +}; + +#endif // LIGHTERBACKGROUND_H diff --git a/lighter-greeter/lightergreeter.cpp b/lighter-greeter/lightergreeter.cpp new file mode 100644 index 00000000..1c5d5e2a --- /dev/null +++ b/lighter-greeter/lightergreeter.cpp @@ -0,0 +1,361 @@ +// SPDX-FileCopyrightText: 2015 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "lightergreeter.h" +#include "timewidget.h" +#include "dlineeditex.h" +#include "transparentbutton.h" +#include "useravatar.h" +#include "public_func.h" +#include "dconfig_helper.h" + +#define AVATAR_ICON_SIZE UserAvatar::AvatarSmallSize +#define AVATAR_SIZE UserAvatar::AvatarLargeSize +#define SPACING 10 + +LighterGreeter::LighterGreeter(QWidget *parent) + : QWidget(parent) + , m_mainLayout(new QVBoxLayout(this)) + , m_loginFrame(new DBlurEffectWidget(this)) + , m_avatar(new UserAvatar(this)) + , m_userCbx(new QComboBox(this)) + , m_passwordEdit(new DLineEditEx(this)) + , m_sessionCbx(new QComboBox(this)) + , m_loginBtn(new TransparentButton(this)) + , m_switchGreeter(new QPushButton(tr("Standard Mode"), this)) + , m_greeter(new QLightDM::Greeter(this)) + , m_sessionModel(new QLightDM::SessionsModel(this)) + , m_allowSwitchToWayland(DConfigHelper::instance()->getConfig("allowSwitchingToWayland", false).toBool()) + , m_defaultSessionName(DConfigHelper::instance()->getConfig("defaultSession", "deepin").toString()) +{ + if (!m_greeter->connectSync()) { + qCritical() << "Connect sync failed"; + close(); + } + + initUI(); + initConnections(); +} + +void LighterGreeter::initUI() +{ + // 顶部区域 + m_mainLayout->addWidget(new TimeWidget(this), 1, Qt::AlignCenter); + + // 中间区域 + QVBoxLayout *layout = new QVBoxLayout; + QVBoxLayout *vLayout = new QVBoxLayout(m_loginFrame); + vLayout->setContentsMargins(SPACING, SPACING, SPACING, SPACING); + vLayout->addSpacing(SPACING + (AVATAR_SIZE / 2)); + vLayout->addWidget(m_userCbx, 0, Qt::AlignCenter); + vLayout->addWidget(m_passwordEdit, 0, Qt::AlignCenter); + + m_loginFrame->setMaskColor(DBlurEffectWidget::LightColor); + m_loginFrame->setMaskAlpha(70); + m_loginFrame->setBlurRectXRadius(15); + m_loginFrame->setBlurRectYRadius(15); + m_loginFrame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + m_loginFrame->setMaximumSize(1152, 300); + m_userCbx->setMinimumWidth(300); + m_passwordEdit->setMinimumWidth(300); + m_passwordEdit->setContextMenuPolicy(Qt::NoContextMenu); + m_passwordEdit->setSecureInputEnabled(true); + m_passwordEdit->lineEdit()->setAlignment(Qt::AlignCenter); + m_passwordEdit->setClearButtonEnabled(false); + m_passwordEdit->setEchoMode(QLineEdit::Password); + m_passwordEdit->setFocusPolicy(Qt::StrongFocus); + m_passwordEdit->lineEdit()->setValidator(new QRegExpValidator(QRegExp("^[ -~]+$"))); + + m_loginBtn->setIcon(DStyle::SP_LockElement); + + auto lockPalette = m_loginBtn->palette(); + QColor color = lockPalette.color(QPalette::Active, QPalette::Highlight); + lockPalette.setColor(QPalette::Disabled, QPalette::Highlight, color); + m_loginBtn->setPalette(lockPalette); + + // 头像始终在LoginFrame区域的上部中间位置 + m_avatar->setFocusPolicy(Qt::NoFocus); + m_avatar->setIcon("/var/lib/AccountsService/icons/guest.png"); + m_avatar->setAvatarSize(AVATAR_ICON_SIZE); + + layout->addStretch(); + layout->addWidget(m_loginFrame, 0, Qt::AlignCenter); + layout->addWidget(m_loginBtn, 0, Qt::AlignCenter); + layout->addSpacing(10); + layout->addStretch(); + + m_mainLayout->addLayout(layout, 5); + + /* 整体布局,横向1:5:1,纵向1:1:1 + |---------------------------| + | | | | + | | Time | | + |---------------------------| + | | | | + | | Login | | + |---------------------------| + | | | | + | | | s | + |---------------------------| + */ + + // 右下角区域 + DBlurEffectWidget *controlFrame = new DBlurEffectWidget(this); + QHBoxLayout *hLayout = new QHBoxLayout(controlFrame); + hLayout->setContentsMargins(SPACING, SPACING, SPACING, SPACING); + hLayout->addWidget(m_sessionCbx, 0, Qt::AlignCenter); + hLayout->addWidget(m_switchGreeter, 0, Qt::AlignCenter); + + controlFrame->setMaskColor(DBlurEffectWidget::LightColor); + controlFrame->setMaskAlpha(70); + controlFrame->setBlurRectXRadius(15); + controlFrame->setBlurRectYRadius(15); + + controlFrame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + m_mainLayout->addWidget(controlFrame, 1, Qt::AlignRight); + + m_userCbx->setModel(new QLightDM::UsersModel(this)); + + for (int i = 0; i < m_sessionModel->rowCount(QModelIndex()); ++i) { + const QString &sessionName = m_sessionModel->data(m_sessionModel->index(i), QLightDM::SessionsModel::IdRole).toString(); + QString displayName = (sessionName == "deepin") ? "X11" : sessionName; + m_sessionCbx->addItem(displayName, sessionName); + } + + if (!m_allowSwitchToWayland) { + m_sessionCbx->removeItem(m_sessionCbx->findData("Wayland")); + } + + if (!m_defaultSessionName.isEmpty()) { + m_sessionCbx->setCurrentIndex(m_sessionCbx->findData(m_defaultSessionName)); + } + + m_sessionCbx->setVisible(m_sessionCbx->count() > 1); + + m_loginFrame->installEventFilter(this); + installEventFilter(this); + + // Select last user + const QString &user = DConfigHelper::instance()->getConfig("lastUser", QString()).toString(); + int index = m_userCbx->findText(user); + if (index != -1) + m_userCbx->setCurrentIndex(index); + + QMetaObject::invokeMethod(this, &LighterGreeter::updateFocus, Qt::QueuedConnection); +} + +void LighterGreeter::initConnections() +{ + connect(m_passwordEdit, &DLineEditEx::returnPressed, this, &LighterGreeter::onStartAuthentication); + connect(m_passwordEdit, &DLineEditEx::textChanged, this, [ = ] { + m_passwordEdit->setAlert(false); + m_passwordEdit->hideAlertMessage(); + }); + connect(m_userCbx, QOverload::of(&QComboBox::currentIndexChanged), this, &LighterGreeter::updateFocus); + connect(m_loginBtn, &TransparentButton::clicked, this, &LighterGreeter::onStartAuthentication); + connect(m_switchGreeter, &QPushButton::clicked, this, &LighterGreeter::resetToNormalGreeter); + + connect(m_greeter, &QLightDM::Greeter::authenticationComplete, this, &LighterGreeter::onAuthenticationComplete); + connect(m_greeter, &QLightDM::Greeter::showPrompt, this, &LighterGreeter::onShowPrompt); + connect(m_greeter, &QLightDM::Greeter::showMessage, this, &LighterGreeter::onShowMessage); +} + +void LighterGreeter::respond() +{ + // Respond to prompt with password text and disable window + m_greeter->respond(m_passwordEdit->text()); + + m_userCbx->setEnabled(false); + m_passwordEdit->setEnabled(false); + m_loginBtn->setEnabled(false); + m_sessionCbx->setEnabled(false); + m_switchGreeter->setEnabled(false); + + // Start password field animation + m_passwordEdit->startAnimation(); +} + +void LighterGreeter::onStartAuthentication() +{ + // Cancel ongoing authentication + if (m_greeter->inAuthentication()) { + m_greeter->cancelAuthentication(); + } + + // Begin new authentication process with selected user + int index = m_userCbx->currentIndex(); + const QString &userName = m_userCbx->itemData(index, QLightDM::UsersModel::NameRole).toString(); + qInfo() << "Start authentication, user: " << userName; + m_greeter->authenticate(userName); + + // Set focus to password field + m_passwordEdit->setFocus(); +} + +void LighterGreeter::onAuthenticationComplete() +{ + qInfo() << "Authentication complete"; + if (m_greeter->isAuthenticated()) { + auto startLogin = [this](const QString & session) { + // Update cache with user information + DConfigHelper::instance()->setConfig("lastUser", m_userCbx->currentText()); + + // Hide current window and emit signal to start new session + this->setVisible(false); + Q_EMIT authFinished(); + + // Set cursor to system default + setRootWindowCursor(); + + // Start session synchronization + QMetaObject::invokeMethod(m_greeter, "startSessionSync", Qt::QueuedConnection + , Q_ARG(QString, session)); + }; + + startLogin(m_sessionCbx->currentData().toString()); + } else { + qInfo() << "Authentication failed"; + } +} + +void LighterGreeter::onShowPrompt(QString promptText, int promptType) +{ + qInfo() << "Showing prompt, text: " << promptText << ", type: " << promptType; + + // Stop password field animation and enable window + m_passwordEdit->stopAnimation(); + + m_userCbx->setEnabled(true); + m_passwordEdit->setEnabled(true); + m_loginBtn->setEnabled(true); + m_sessionCbx->setEnabled(true); + m_switchGreeter->setEnabled(true); + + // Determine type of prompt being displayed + auto type = static_cast(promptType); + switch (type) { + case QLightDM::Greeter::PromptType::PromptTypeSecret: + case QLightDM::Greeter::PromptType::PromptTypeQuestion: + respond(); + + // Not need show just respond password + // m_passwordEdit->clear(); + // m_passwordEdit->setFocus(); + // m_passwordEdit->setPlaceholderText(promptText); + break; + } +} + +void LighterGreeter::onShowMessage(QString messageText, int messageType) +{ + qInfo() << "Showing message, text: " << messageText << ", type: " << messageType; + + // Stop password field animation and enable window + m_passwordEdit->stopAnimation(); + + m_userCbx->setEnabled(true); + m_passwordEdit->setEnabled(true); + m_loginBtn->setEnabled(true); + m_sessionCbx->setEnabled(true); + m_switchGreeter->setEnabled(true); + + // Determine type of message being displayed + auto type = static_cast(messageType); + switch (type) { + case QLightDM::Greeter::MessageType::MessageTypeInfo: + // Do nothing for info messages + break; + case QLightDM::Greeter::MessageType::MessageTypeError: + // Clear password field, set alert flag, and show error message for error messages + if (m_passwordEdit->isVisible()) { + m_passwordEdit->setText(QString()); + m_passwordEdit->setAlert(true); + m_passwordEdit->showAlertMessage(messageText); + m_passwordEdit->setFocus(); + m_passwordEdit->lineEdit()->setFocus(); + } + break; + } +} + +void LighterGreeter::resetToNormalGreeter() +{ + // If it exits abnormally, try to pull up the normal Greeter, this part is handled in the script + qApp->exit(-1); +} + +void LighterGreeter::updateFocus() +{ + // Clear password field + m_passwordEdit->setText(QString()); + + m_passwordEdit->setVisible(true); + + const QString &userName = m_userCbx->itemData(m_userCbx->currentIndex(), QLightDM::UsersModel::NameRole).toString(); + + QFile group("/etc/group"); + if (group.open(QIODevice::ReadOnly)) { + QByteArray content = group.readAll(); + QList list = content.split('\n'); + for (auto item : list) { + // Wether current user is in group nopasswordlogin + if (item.startsWith("nopasswdlogin") && item.endsWith(userName.toStdString().data())) { + m_passwordEdit->setVisible(false); + m_loginBtn->setFocus(); + + this->setTabOrder(m_loginBtn, m_sessionCbx); + this->setTabOrder(m_sessionCbx, m_switchGreeter); + this->setTabOrder(m_switchGreeter, m_userCbx); + this->setTabOrder(m_userCbx, m_loginBtn); + + return; + } + } + } + + m_passwordEdit->setFocus(); + m_passwordEdit->lineEdit()->setFocus(); + + this->setTabOrder(m_loginBtn, m_sessionCbx); + this->setTabOrder(m_sessionCbx, m_switchGreeter); + this->setTabOrder(m_switchGreeter, m_userCbx); + this->setTabOrder(m_userCbx, m_passwordEdit); + this->setTabOrder(m_passwordEdit, m_loginBtn); +} + +bool LighterGreeter::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == this && event->type() == QEvent::Show) { + // Set focus to password field when window is displayed + if (!qgetenv("XDG_SESSION_TYPE").startsWith("wayland")) + activateWindow(); + + updateFocus(); + } else if ((watched == this || watched == m_loginFrame) && event->type() == QEvent::Resize) { + int x = m_loginFrame->mapToGlobal(QPoint(0, 0)).x() + ((m_loginFrame->width() - AVATAR_SIZE) / 2); + int y = m_loginFrame->mapToGlobal(QPoint(0, 0)).y() - (AVATAR_SIZE / 2); + + m_avatar->move(mapFromGlobal(QPoint(x, y))); + } + + return QWidget::eventFilter(watched, event); +} diff --git a/lighter-greeter/lightergreeter.h b/lighter-greeter/lightergreeter.h new file mode 100644 index 00000000..0c0bdaf4 --- /dev/null +++ b/lighter-greeter/lightergreeter.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef LIGHTERGREETER_H +#define LIGHTERGREETER_H + +#include + +#include + +class QLineEdit; +class QVBoxLayout; +class QListView; +class QComboBox; +class QPushButton; +class QLabel; + +namespace QLightDM { +class Greeter; +class SessionsModel; +class UsersModel; +} +DWIDGET_BEGIN_NAMESPACE +class DBlurEffectWidget; +DWIDGET_END_NAMESPACE + +class DLineEditEx; +class TransparentButton; +class UserAvatar; + +DWIDGET_USE_NAMESPACE + +class LighterGreeter : public QWidget +{ + Q_OBJECT +public: + explicit LighterGreeter(QWidget *parent = nullptr); + + void initUI(); + void initConnections(); + +Q_SIGNALS: + void authFinished(); + +public Q_SLOTS: + void onStartAuthentication(); + void onAuthenticationComplete(); + void onShowPrompt(QString promptText, int promptType); + void onShowMessage(QString messageText, int messageType); + void resetToNormalGreeter(); + +private Q_SLOTS: + void respond(); + void updateFocus(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + // 布局控件 + QVBoxLayout *m_mainLayout; + DBlurEffectWidget *m_loginFrame; + UserAvatar *m_avatar; + QComboBox *m_userCbx; + DLineEditEx *m_passwordEdit; + QComboBox *m_sessionCbx; + TransparentButton *m_loginBtn; + QPushButton *m_switchGreeter; + + // greeter + QLightDM::Greeter *m_greeter; + QLightDM::SessionsModel *m_sessionModel; + + // variant + bool m_allowSwitchToWayland; + QString m_defaultSessionName; +}; + +#endif // LIGHTERGREETER_H diff --git a/lighter-greeter/lighterscreenmanager.cpp b/lighter-greeter/lighterscreenmanager.cpp new file mode 100644 index 00000000..fa3cd710 --- /dev/null +++ b/lighter-greeter/lighterscreenmanager.cpp @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "lighterscreenmanager.h" +#include "abstractfullbackgroundinterface.h" + +#include +#include +#include + +LighterScreenManager::LighterScreenManager(std::function function, QObject *parent) + : QObject(parent) + , m_registerFun(function) +{ + Q_ASSERT(m_registerFun); + + connect(qApp, &QGuiApplication::screenAdded, this, &LighterScreenManager::screenCountChanged); + connect(qApp, &QGuiApplication::screenRemoved, this, &LighterScreenManager::screenCountChanged); + + screenCountChanged(); +} + +void LighterScreenManager::screenCountChanged() +{ + QList screens = m_screenContents.values(); + + // 找到过期的screen指针 + QList screens_to_remove; + for (const auto &s : screens) { + if (!qApp->screens().contains(s)) + screens_to_remove.append(s); + } + + // 找出新增的screen指针 + QList screens_to_add; + for (const auto &s : qApp->screens()) { + if (!screens.contains(s)) { + screens_to_add.append(s); + } + } + + // 释放过期的资源 + for (auto &s : screens_to_remove) { + disconnect(s); + auto backgroundFrame = m_screenContents.key(s); + if (backgroundFrame) { + // @note 创建的界面并不释放,后面可以继续复用,如果为了内存考虑,也可以启动一个定时器,在一分钟后释放(释放后要从map中remove) + backgroundFrame->setVisible(false); + } + s = nullptr; + } + + // 处理新增的资源 + for (const auto &s : screens_to_add) { + s->setOrientationUpdateMask(Qt::PrimaryOrientation + | Qt::LandscapeOrientation + | Qt::PortraitOrientation + | Qt::InvertedLandscapeOrientation + | Qt::InvertedPortraitOrientation); + + // 显示器信息发生任何变化时,都应该重新刷新一次显示情况 + connect(s, &QScreen::geometryChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::availableGeometryChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::physicalSizeChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::physicalDotsPerInchChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::logicalDotsPerInchChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::virtualGeometryChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::primaryOrientationChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::orientationChanged, this, &LighterScreenManager::handleScreenChanged); + connect(s, &QScreen::refreshRateChanged, this, &LighterScreenManager::handleScreenChanged); + + auto findContentNotUsed = [ = ](QMap map) ->QWidget * { + QMapIterator it(map); + while (it.hasNext()) + { + it.next(); + if (!it.value() && it.key()) { + return it.key(); + } + } + return nullptr; + }; + + // try to find a content frame not used now + QWidget *content = findContentNotUsed(m_screenContents); + + // or create new content frame + if (!content) { + content = m_registerFun(s); + } + + content->setVisible(true); + + m_screenContents.insert(content, s); + } +} + +void LighterScreenManager::handleScreenChanged() +{ + for (QWidget *w : m_screenContents.keys()) { + auto inter = dynamic_cast(w); + if (inter && m_screenContents.value(w)) { + inter->setScreen(m_screenContents.value(w)); + } + } +} diff --git a/lighter-greeter/lighterscreenmanager.h b/lighter-greeter/lighterscreenmanager.h new file mode 100644 index 00000000..7e41ad9a --- /dev/null +++ b/lighter-greeter/lighterscreenmanager.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef LIGHTERSCREENMANAGER_H +#define LIGHTERSCREENMANAGER_H + +#include +#include +#include +#include + +class LighterScreenManager : public QObject +{ + Q_OBJECT +public: + explicit LighterScreenManager(std::function function, QObject *parent = nullptr); + + typedef QPointer ScreenPtr; + +Q_SIGNALS: + void copyModeChanged(bool isCopyMode); + +public Q_SLOTS: + void screenCountChanged(); + void handleScreenChanged(); + +private: + std::function m_registerFun; + QMap m_screenContents; +}; + +#endif // LIGHTERSCREENMANAGER_H diff --git a/lighter-greeter/main.cpp b/lighter-greeter/main.cpp new file mode 100644 index 00000000..8e0e6a1f --- /dev/null +++ b/lighter-greeter/main.cpp @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2015 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include +#include + +#include +#include + +#include "lightergreeter.h" +#include "lighterbackground.h" +#include "lighterscreenmanager.h" +#include "public_func.h" + +DCORE_USE_NAMESPACE +DGUI_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + // 正确加载dxcb插件 + //for qt5platform-plugins load DPlatformIntegration or DPlatformIntegrationParent + if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { + setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); + } + + DGuiApplicationHelper::setAttribute(DGuiApplicationHelper::UseInactiveColorGroup, false); + + // qt默认当最后一个窗口析构后,会自动退出程序,这里设置成false,防止插拔时,没有屏幕,导致进程退出 + QApplication::setQuitOnLastWindowClosed(false); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + + QApplication a(argc, argv); + qApp->setOrganizationName("deepin"); + qApp->setApplicationName("org.deepin.dde.lightdm-deepin-greeter"); + setAppType(APP_TYPE_LOGIN); + qApp->setProperty("dssAppType", APP_TYPE_LOGIN); + + DPalette pa = DGuiApplicationHelper::instance()->standardPalette(DGuiApplicationHelper::LightType); + pa.setColor(QPalette::Normal, DPalette::WindowText, QColor("#FFFFFF")); + pa.setColor(QPalette::Normal, DPalette::Text, QColor("#FFFFFF")); + pa.setColor(QPalette::Normal, DPalette::AlternateBase, QColor(0, 0, 0, 76)); + pa.setColor(QPalette::Normal, DPalette::Button, QColor(255, 255, 255, 76)); + pa.setColor(QPalette::Normal, DPalette::Light, QColor(255, 255, 255, 76)); + pa.setColor(QPalette::Normal, DPalette::Dark, QColor(255, 255, 255, 76)); + pa.setColor(QPalette::Normal, DPalette::ButtonText, QColor("#FFFFFF")); + + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::WindowText, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::Text, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::AlternateBase, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::Button, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::Light, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::Dark, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::generatePaletteColor(pa, DPalette::ButtonText, DGuiApplicationHelper::LightType); + DGuiApplicationHelper::instance()->setApplicationPalette(pa); + + setPointer(); + + auto createFrame = [&](QPointer screen) -> QWidget * { + // 所有的界面共用一块内容 + static LighterGreeter *g_greeter = new LighterGreeter; + + LighterBackground *bg = new LighterBackground(g_greeter); + QObject::connect(g_greeter, &LighterGreeter::authFinished, bg, &LighterBackground::onAuthFinished); + bg->setScreen(screen); + return bg; + }; + + new LighterScreenManager(createFrame); + + return a.exec(); +} diff --git a/lupdate.sh b/lupdate.sh index a878242b..ba29ec63 100755 --- a/lupdate.sh +++ b/lupdate.sh @@ -1,4 +1,8 @@ #!/bin/bash -lupdate ./ -ts -no-obsolete -locations none translations/dde-session-shell_en.ts +lupdate ./interface ./src ./tests -ts -no-obsolete -locations none translations/dde-session-shell_en.ts +cd plugins/login-gesture +./lupdate.sh +cd ../../ + #tx push -s -b m20 # Push the files that need to be translated #tx pull -s -b m20 # Pull the translated files diff --git a/misc/images/auth/passkey.svg b/misc/images/auth/passkey.svg new file mode 100644 index 00000000..8c250617 --- /dev/null +++ b/misc/images/auth/passkey.svg @@ -0,0 +1,10 @@ + + + icon/login/fido + + + + + + + \ No newline at end of file diff --git a/misc/images/domainUser.svg b/misc/images/domainUser.svg new file mode 100644 index 00000000..6f847fdb --- /dev/null +++ b/misc/images/domainUser.svg @@ -0,0 +1,25 @@ + + + 分组@1x + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/misc/images/dss_warning.svg b/misc/images/dss_warning.svg new file mode 100644 index 00000000..1bcf948f --- /dev/null +++ b/misc/images/dss_warning.svg @@ -0,0 +1,29 @@ + + + icon/warning + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/misc/images/password-hide.svg b/misc/images/password-hide.svg new file mode 100644 index 00000000..4af7cc03 --- /dev/null +++ b/misc/images/password-hide.svg @@ -0,0 +1,8 @@ + + + icon/login/password-hide + + + + + \ No newline at end of file diff --git a/misc/images/password-shown.svg b/misc/images/password-shown.svg new file mode 100644 index 00000000..2955a95b --- /dev/null +++ b/misc/images/password-shown.svg @@ -0,0 +1,10 @@ + + + icon/login/password-shown + + + + + + + \ No newline at end of file diff --git a/misc/images/select.svg b/misc/images/select.svg index c71125b2..3d0141be 100644 --- a/misc/images/select.svg +++ b/misc/images/select.svg @@ -1,15 +1,10 @@ - - select - Created with Sketch. - - - - - - - + list_select_dark + + + + \ No newline at end of file diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt deleted file mode 100644 index b1ff7c4f..00000000 --- a/modules/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(examples) -add_subdirectory(login) diff --git a/modules/examples/CMakeLists.txt b/modules/examples/CMakeLists.txt deleted file mode 100644 index 547cd816..00000000 --- a/modules/examples/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# add_subdirectory(login) -add_subdirectory(network) -#add_subdirectory(webview) diff --git a/modules/examples/login/login.json b/modules/examples/login/login.json deleted file mode 100644 index c08700b9..00000000 --- a/modules/examples/login/login.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api": "1.2.3" -} diff --git a/modules/examples/login/login_module.cpp b/modules/examples/login/login_module.cpp deleted file mode 100644 index c2fdeb7c..00000000 --- a/modules/examples/login/login_module.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "login_module.h" - -#include -#include - -#include - -#include - -namespace dss { -namespace module { - -LoginModule::LoginModule(QObject *parent) - : QObject(parent) - , m_callbackFun(nullptr) - , m_loginWidget(nullptr) -{ - setObjectName(QStringLiteral("LoginModule")); -} - -LoginModule::~LoginModule() -{ - if (m_loginWidget) { - delete m_loginWidget; - } -} - -void LoginModule::init() -{ - initUI(); -} - -void LoginModule::initUI() -{ - if (m_loginWidget) { - return; - } - m_loginWidget = new QWidget; - m_loginWidget->setAccessibleName(QStringLiteral("LoginWidget")); - m_loginWidget->setFixedSize(200, 100); - QVBoxLayout *loginLayout = new QVBoxLayout(m_loginWidget); - - QWebEngineView *webView = new QWebEngineView(m_loginWidget); - QWebEnginePage *webPage = new QWebEnginePage(m_loginWidget); - QWebChannel *webChannel = new QWebChannel(m_loginWidget); - webView->setPage(webPage); - webPage->setWebChannel(webChannel); - webView->setContextMenuPolicy(Qt::NoContextMenu); - - loginLayout->addWidget(webView); - - webView->load(QUrl("https://www.baidu.com")); - - connect(webView, &QWebEngineView::loadFinished, this, [this]{ - QTimer::singleShot(1000, this, [this]{ - AuthCallbackData data; - data.account = "uos"; - data.token = "1"; - data.result = true; - m_callbackFun(&data, m_callback->ContainerPtr); - }); - - }); -} - -void LoginModule::setAuthFinishedCallback(AuthCallback *callback) -{ - m_callback = callback; - m_callbackFun = callback->callbackFun; -} - -} // namespace module -} // namespace dss diff --git a/modules/examples/login/login_module.h b/modules/examples/login/login_module.h deleted file mode 100644 index 26811641..00000000 --- a/modules/examples/login/login_module.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef LOGIN_MODULE_H -#define LOGIN_MODULE_H - -#include "login_module_interface.h" - -namespace dss { -namespace module { - -class LoginModule : public QObject - , public LoginModuleInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules.Login" FILE "login.json") - Q_INTERFACES(dss::module::LoginModuleInterface) - -public: - explicit LoginModule(QObject *parent = nullptr); - ~LoginModule() override; - - void init() override; - - inline QString key() const override { return objectName(); } - inline QWidget *content() override { return m_loginWidget; } - - void setAuthFinishedCallback(AuthCallback *callback) override; - -private: - void initUI(); - -private: - AuthCallback *m_callback; - AuthCallbackFun m_callbackFun; - QWidget *m_loginWidget; -}; - -} // namespace module -} // namespace dss -#endif // LOGIN_MODULE_H diff --git a/modules/examples/network/network.json b/modules/examples/network/network.json deleted file mode 100644 index c08700b9..00000000 --- a/modules/examples/network/network.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api": "1.2.3" -} diff --git a/modules/examples/webview/webview.json b/modules/examples/webview/webview.json deleted file mode 100644 index c08700b9..00000000 --- a/modules/examples/webview/webview.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api": "1.2.3" -} diff --git a/modules/examples/webview/webview_content.cpp b/modules/examples/webview/webview_content.cpp deleted file mode 100644 index 8331ecec..00000000 --- a/modules/examples/webview/webview_content.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "webview_content.h" - -#include - -namespace dss { -namespace module { - -WebviewContent::WebviewContent(QWidget *parent) - : QWidget(parent) - , m_mainLayout(nullptr) - , m_webview(nullptr) -{ - setObjectName(QStringLiteral("WebviewContent")); - setAccessibleName(QStringLiteral("WebviewContent")); - - setFixedSize(600, 500); - - initUI(); -} - -void WebviewContent::initUI() -{ - m_mainLayout = new QVBoxLayout(this); - - m_webview = new QWebEngineView(this); - m_webview->load(QUrl("http://www.baidu.com")); - - m_mainLayout->addWidget(m_webview); -} - -} // namespace module -} // namespace dss diff --git a/modules/examples/webview/webview_content.h b/modules/examples/webview/webview_content.h deleted file mode 100644 index 564c4735..00000000 --- a/modules/examples/webview/webview_content.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef WEBVIEWCONTENT_H -#define WEBVIEWCONTENT_H - -#include -#include - -class QVBoxLayout; - -namespace dss { -namespace module { - -class WebviewContent : public QWidget -{ - Q_OBJECT - -public: - explicit WebviewContent(QWidget *parent = nullptr); - -private: - void initUI(); - -private: - QVBoxLayout *m_mainLayout; - QWebEngineView *m_webview; -}; - -} // namespace module -} // namespace dss -#endif // WEBVIEWCONTENT_H diff --git a/modules/examples/webview/webview_module.cpp b/modules/examples/webview/webview_module.cpp deleted file mode 100644 index 3fefbdac..00000000 --- a/modules/examples/webview/webview_module.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "webview_module.h" - -#include - -namespace dss { -namespace module { - -WebviewModule::WebviewModule(QObject *parent) - : QObject(parent) - , m_webviewContent(nullptr) -{ - setObjectName(QStringLiteral("WebviewModule")); -} - -WebviewModule::~WebviewModule() -{ - if (m_webviewContent) { - delete m_webviewContent; - } -} - -void WebviewModule::init() -{ - initUI(); -} - -void WebviewModule::initUI() -{ - if (m_webviewContent) { - return; - } - m_webviewContent = new WebviewContent(); -} - -} // namespace module -} // namespace dss diff --git a/modules/login/CMakeLists.txt b/modules/login/CMakeLists.txt deleted file mode 100644 index 41b3027a..00000000 --- a/modules/login/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets WebEngineWidgets REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets WebEngineWidgets REQUIRED) - -include_directories( - ${DFrameworkDBus_INCLUDE_DIRS} - global -) - -link_libraries( - ${Qt_LIBS} - Qt${QT_VERSION_MAJOR}::Widgets - Qt${QT_VERSION_MAJOR}::WebEngineWidgets -) - -set(LIB_NAME login) - -aux_source_directory(. SRCS) - -# add_library(${LIB_NAME} STATIC ${SRCS}) - -add_library(${LIB_NAME} SHARED ${SRCS}) - -install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/modules/login/login.json b/modules/login/login.json deleted file mode 100644 index c08700b9..00000000 --- a/modules/login/login.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "api": "1.2.3" -} diff --git a/modules/login/login_module.cpp b/modules/login/login_module.cpp deleted file mode 100644 index b4f6fc1e..00000000 --- a/modules/login/login_module.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "login_module.h" - -#include -#include - -#include - -#include - -namespace dss { -namespace module { - -LoginModule::LoginModule(QObject *parent) - : QObject(parent) - , m_callbackFun(nullptr) - , m_callbackData(new AuthCallbackData) - , m_loginWidget(nullptr) -{ - setObjectName(QStringLiteral("LoginModule")); - - m_callbackData->account = "uos"; - m_callbackData->token = "1"; - m_callbackData->result = 0; -} - -LoginModule::~LoginModule() -{ - if (m_loginWidget) { - delete m_loginWidget; - } - if (m_callbackData) { - delete m_callbackData; - } -} - -void LoginModule::init() -{ - initUI(); -} - -void LoginModule::initUI() -{ - if (m_loginWidget) { - return; - } - m_loginWidget = new QWidget; - m_loginWidget->setAccessibleName(QStringLiteral("LoginWidget")); - m_loginWidget->setMinimumSize(280, 280); - QVBoxLayout *loginLayout = new QVBoxLayout(m_loginWidget); - - QWebEngineView *webView = new QWebEngineView(m_loginWidget); - QWebEnginePage *webPage = new QWebEnginePage(m_loginWidget); - QWebChannel *webChannel = new QWebChannel(m_loginWidget); - webView->setPage(webPage); - webPage->setWebChannel(webChannel); - webView->setContextMenuPolicy(Qt::NoContextMenu); - - loginLayout->addWidget(webView); - - webView->load(QUrl("https://wx.qq.com/")); -} - -void LoginModule::setAuthFinishedCallback(AuthCallback *callback) -{ - m_callback = callback; - m_callbackFun = callback->callbackFun; - - // 当认证完成,调用这个方法 - m_callbackFun(m_callbackData, m_callback->app_data); -} - -} // namespace module -} // namespace dss diff --git a/modules/login/login_module.h b/modules/login/login_module.h deleted file mode 100644 index 4882f91e..00000000 --- a/modules/login/login_module.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef LOGIN_MODULE_H -#define LOGIN_MODULE_H - -#include "login_module_interface.h" - -namespace dss { -namespace module { - -class LoginModule : public QObject - , public LoginModuleInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules.Login" FILE "login.json") - Q_INTERFACES(dss::module::LoginModuleInterface) - -public: - explicit LoginModule(QObject *parent = nullptr); - ~LoginModule() override; - - void init() override; - - inline QString key() const override { return objectName(); } - inline QWidget *content() override { return m_loginWidget; } - - void setAuthFinishedCallback(AuthCallback *callback) override; - -private: - void initUI(); - -private: - AuthCallback *m_callback; - AuthCallbackFun m_callbackFun; - AuthCallbackData *m_callbackData; - QWidget *m_loginWidget; -}; - -} // namespace module -} // namespace dss -#endif // LOGIN_MODULE_H diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 00000000..a98068bd --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,6 @@ +if (DISABLE_DSS_SNIPE) + add_subdirectory(one-key-login) + add_subdirectory("login-gesture") +endif() +# add_subdirectory(examples) +# add_subdirectory(assist_login) diff --git a/plugins/assist_login/CMakeLists.txt b/plugins/assist_login/CMakeLists.txt new file mode 100644 index 00000000..6cfeea0d --- /dev/null +++ b/plugins/assist_login/CMakeLists.txt @@ -0,0 +1,23 @@ +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network REQUIRED) +find_package(PkgConfig REQUIRED) + +pkg_check_modules(SSL REQUIRED IMPORTED_TARGET libcrypto libssl openssl) + +link_libraries( + ${Qt_LIBS} + Qt${QT_VERSION_MAJOR}::Widgets + PkgConfig::SSL + Dtk${DTK_VERSION_MAJOR}::Widget + Dtk${DTK_VERSION_MAJOR}::Core +) + +set(LIB_NAME assist-login) + +set(LIB_NAME_INTERface assist_Login_interface) + +aux_source_directory(. SRCS) + +add_library(${LIB_NAME} SHARED ${SRCS}) + +add_subdirectory(interface) +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) \ No newline at end of file diff --git a/plugins/assist_login/assist_login_module.cpp b/plugins/assist_login/assist_login_module.cpp new file mode 100644 index 00000000..8b58584f --- /dev/null +++ b/plugins/assist_login/assist_login_module.cpp @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "assist_login_module.h" + +namespace dss { +namespace module { + +AssistLoginModule::AssistLoginModule(QObject *parent) + : QObject(parent) + , m_callbackFun(nullptr) + , m_callbackData(new AuthCallbackData) + , m_messageCallbackFunc(nullptr) + , m_work(nullptr) + , m_mainWidget(nullptr) +{ + setObjectName(QStringLiteral("AssistLoginModule")); +} + +AssistLoginModule::~AssistLoginModule() +{ + if (m_mainWidget) { + delete m_mainWidget; + } + if (m_callbackData) { + delete m_callbackData; + } +} + +void AssistLoginModule::init() +{ + m_work = new AssistLoginWork(this); + m_work->moveToThread(qApp->thread()); + initUI(); + initConnect(); +} + +void AssistLoginModule::reset() +{ + init(); +} + +void AssistLoginModule::initUI() +{ + if (m_mainWidget) { + return; + } + + m_mainWidget = new AssistLoginWidget; +} + +void AssistLoginModule::setCallback(LoginCallBack *callback) +{ + m_callback = callback; + m_callbackFun = callback->authCallbackFun; +} + +void AssistLoginModule::initConnect() +{ + if (!m_mainWidget || !m_work) { + return; + } + connect(m_work, &AssistLoginWork::sendAuthToken, this, &AssistLoginModule::sendAuthToken); + connect(m_mainWidget, &AssistLoginWidget::sendAuth, this, [this](const QString & account, const QString & token) { + if (m_callbackFun == nullptr) { + return; + } + AuthCallbackData data; + data.account = account.toStdString(); + data.token = token.toStdString(); + data.result = AuthResult::Success; + + m_callbackFun(&data, m_callback->app_data); + }, Qt::DirectConnection); + + connect(m_mainWidget, &AssistLoginWidget::startService, m_work, &AssistLoginWork::onStartService); + connect(m_mainWidget, &AssistLoginWidget::stopService, m_work, &AssistLoginWork::onStopService); +} + +std::string AssistLoginModule::onMessage(const std::string &message) +{ + qInfo() << Q_FUNC_INFO; + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(QByteArray::fromStdString(message), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + qWarning() << Q_FUNC_INFO << "Failed to obtain message from shell!: " << QString::fromStdString(message); + return ""; + } + + QJsonObject retObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + + QJsonObject msgObj = messageDoc.object(); + QString cmdType = msgObj.value("CmdType").toString(); + QJsonObject data = msgObj.value("Data").toObject(); + qInfo() << "Cmd type: " << cmdType; + if (cmdType == "CurrentUserChanged") { + + } else if (cmdType == "GetConfigs") { + QJsonObject retDataObj; + retDataObj["ShowAvatar"] = false; + retDataObj["ShowUserName"] = false; + retDataObj["ShowSwitchButton"] = false; + retDataObj["ShowLockButton"] = false; + retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::StrongDefault; + retDataObj["AuthType"] = AuthType::AT_Password; + + retObj["Data"] = retDataObj; + } + + QJsonDocument doc; + doc.setObject(retObj); + return doc.toJson().toStdString(); +} + +void AssistLoginModule::sendAuthToken(const QString &user, const QString &passwd) +{ + if (m_callbackFun == nullptr) { + return; + } + AuthCallbackData data; + data.account = user.toStdString(); + data.token = passwd.toStdString(); + data.result = AuthResult::Success; + + m_callbackFun(&data, m_callback->app_data); +} + +} +} diff --git a/plugins/assist_login/assist_login_module.h b/plugins/assist_login/assist_login_module.h new file mode 100644 index 00000000..cb3b4d7f --- /dev/null +++ b/plugins/assist_login/assist_login_module.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ASSIST_LOGIN_MODULE_H +#define ASSIST_LOGIN_MODULE_H + +#include "login_module_interface.h" +#include "assist_login_work.h" +#include "assist_login_widget.h" + +namespace dss { +namespace module { + +class AssistLoginModule: public QObject, public LoginModuleInterface +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules.Login" FILE "login.json") + Q_INTERFACES(dss::module::LoginModuleInterface) + +public: + explicit AssistLoginModule(QObject *parent = nullptr); + ~AssistLoginModule() override; + + void init() override; + ModuleType type() const override { return IpcAssistLoginType; } + inline QString key() const override { return objectName(); } + inline QWidget *content() override { return (QWidget *) m_mainWidget; } + void setCallback(LoginCallBack *callback) override; + std::string onMessage(const std::string &) override; + void reset() override; + + +private: + void initUI(); + void initConnect(); + +private Q_SLOTS: + void sendAuthToken(const QString &user, const QString &passwd); + +private: + LoginCallBack *m_callback; + AuthCallbackFun m_callbackFun; + AuthCallbackData *m_callbackData; + MessageCallbackFun m_messageCallbackFunc; + AssistLoginWork *m_work; + AssistLoginWidget *m_mainWidget; +}; + +} +} +#endif //ASSIST_LOGIN_MODULE_H diff --git a/plugins/assist_login/assist_login_widget.cpp b/plugins/assist_login/assist_login_widget.cpp new file mode 100644 index 00000000..5cd3bf58 --- /dev/null +++ b/plugins/assist_login/assist_login_widget.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "assist_login_widget.h" +#include + +#include +#include + +dss::module::AssistLoginWidget::AssistLoginWidget(QWidget *parent) + : QWidget(parent) + , m_spinner(nullptr) + , m_label(nullptr) +{ + init(); +} + +void dss::module::AssistLoginWidget::init() +{ + setAccessibleName(QStringLiteral("LoginWidget")); + setMinimumSize(260, 100); + + QVBoxLayout *layout = new QVBoxLayout(); + + m_spinner = new DTK_WIDGET_NAMESPACE::DSpinner(this); + m_spinner->setFixedSize(40, 40); + m_spinner->start(); + layout->setSpacing(4); + layout->addWidget(m_spinner, 0, Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignVCenter); + m_label = new DTK_WIDGET_NAMESPACE::DLabel(this); + m_label->setFixedSize(125, 40); + m_label->setText(tr("Automatic login")); + m_label->setAlignment(Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignVCenter); + Dtk::Widget::DFontSizeManager::instance()->bind(m_label, Dtk::Widget::DFontSizeManager::T6); + layout->addWidget(m_label, 0, Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignVCenter); + + setLayout(layout); +} + +void dss::module::AssistLoginWidget::hideEvent(QHideEvent *event) +{ + Q_EMIT stopService(); + QWidget::hideEvent(event); +} +void dss::module::AssistLoginWidget::showEvent(QShowEvent *event) +{ + Q_EMIT startService(); + QWidget::showEvent(event); +} diff --git a/plugins/assist_login/assist_login_widget.h b/plugins/assist_login/assist_login_widget.h new file mode 100644 index 00000000..6696eb79 --- /dev/null +++ b/plugins/assist_login/assist_login_widget.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ASSIST_LOGIN_WIDGET_H +#define ASSIST_LOGIN_WIDGET_H + +#include +#include +#include + +namespace dss { + +namespace module { + +class AssistLoginWidget: public QWidget +{ + Q_OBJECT + +public: + explicit AssistLoginWidget(QWidget *parent = nullptr); + +protected: + void hideEvent(QHideEvent *event) override; + void showEvent(QShowEvent *event) override; + +Q_SIGNALS: + void sendAuth(const QString &account, const QString &token); + void stopService(); + void startService(); + + +private: + void init(); + + DTK_WIDGET_NAMESPACE::DSpinner *m_spinner; + DTK_WIDGET_NAMESPACE::DLabel *m_label; +}; +} +} + +#endif //ASSIST_LOGIN_WIDGET_H diff --git a/plugins/assist_login/assist_login_work.cpp b/plugins/assist_login/assist_login_work.cpp new file mode 100644 index 00000000..c6b3427d --- /dev/null +++ b/plugins/assist_login/assist_login_work.cpp @@ -0,0 +1,229 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include + +#include "assist_login_work.h" +#include "dbusconstant.h" + +const QString SocketServiceName = "dde-assist-login"; + +dss::module::AssistLoginWork::AssistLoginWork(QObject *parent) + : QObject(parent) + , m_socketHelper(nullptr) + , m_keyPair(nullptr) +{ + init(); +} + +dss::module::AssistLoginWork::~AssistLoginWork() +{ + if (m_socketHelper) { + delete m_socketHelper; + m_socketHelper = nullptr; + } +} + +void dss::module::AssistLoginWork::init() +{ + m_socketHelper = new SocketHelper(SocketServiceName); + connect(m_socketHelper, &SocketHelper::createPublicEncrypt, this, &AssistLoginWork::onCreatePublicEncrypt); + connect(m_socketHelper, &SocketHelper::createPrivateEncrypt, this, &AssistLoginWork::onCreatePrivateEncrypt); + connect(m_socketHelper, &SocketHelper::getAuthResult, this, &AssistLoginWork::onGetAuthResult); + connect(m_socketHelper, &SocketHelper::startAuth, this, &AssistLoginWork::onStartAuth); + + // 生成RSA的公钥和私钥 + generateRSAKeyPair(); + +} + +void dss::module::AssistLoginWork::onCreatePublicEncrypt() +{ + if (m_socketHelper == nullptr) { + return; + } + const char * key = keyToString(m_keyPair, 1); + m_socketHelper->sendDataToClient(QByteArray(key)); + delete[] key; +} + +void dss::module::AssistLoginWork::onGetAuthResult() +{ + if (m_socketHelper == nullptr) { + return; + } + m_socketHelper->sendDataToClient("onGetAuthResult"); +} + +void dss::module::AssistLoginWork::onStartAuth(const QString &user, const QString &passwd) +{ + qDebug() << Q_FUNC_INFO << user; + QDBusInterface dssInterface(DSS_DBUS::accountsService, DSS_DBUS::accountsPath, DSS_DBUS::accountsService, + QDBusConnection::systemBus()); + QDBusReply data = dssInterface.call("FindUserByName", user); + if (!data.isValid()) { + qWarning() << Q_FUNC_INFO << data.error().message(); + return; + } + QString userPath = data.value(); + if (!userPath.startsWith("/")) { + qDebug() << Q_FUNC_INFO << " wrong account"; + return; + } + + Q_EMIT sendAuthToken(user, passwd); +} + +void dss::module::AssistLoginWork::generateRSAKeyPair() +{ + int bits = 2048; // 设置秘钥长度 + + // 创建RSA对象 + m_keyPair = RSA_new(); + if (m_keyPair == NULL) { + return; + } + + // 生成RSA秘钥对 + BIGNUM *e = BN_new(); + if (e == NULL) { + RSA_free(m_keyPair); + return; + } + + if (BN_set_word(e, RSA_F4) != 1) { + BN_free(e); + RSA_free(m_keyPair); + return; + } + + if (RSA_generate_key_ex(m_keyPair, bits, e, NULL) != 1) { + BN_free(e); + RSA_free(m_keyPair); + return; + } + + BN_free(e); +} + +std::string dss::module::AssistLoginWork::rsaEncrypt(const std::string &plaintext, RSA *publicKey) +{ + int maxEncryptSize = RSA_size(publicKey); + std::string encryptedText; + + // 创建足够大的缓冲区来存储加密结果 + unsigned char *encryptBuffer = new unsigned char[maxEncryptSize]; + int encryptLength = RSA_public_encrypt(plaintext.length(), reinterpret_cast(plaintext.c_str()), + encryptBuffer, publicKey, RSA_PKCS1_PADDING); + if (encryptLength != -1) { + encryptedText.assign(reinterpret_cast(encryptBuffer), encryptLength); + } + + delete[] encryptBuffer; + return encryptedText; +} + +std::string dss::module::AssistLoginWork::rsaDecrypt(const char *encryptedText, RSA *privateKey, int len) +{ + int maxDecryptSize = RSA_size(privateKey); + std::string decryptedText; + + int j = 0, counter = 0; + char c[2]; + unsigned int bytes[2]; + unsigned char UnChar[len]; + + for (j = 0; j < len; j += 2) { + if (0 == j % 2) { + c[0] = encryptedText[j]; + c[1] = encryptedText[j + 1]; + sscanf(c, "%02x", &bytes[0]); + UnChar[counter] = bytes[0]; + std::cout << static_cast(UnChar[counter]); + counter++; + } + } + + // 创建足够大的缓冲区来存储解密结果 + unsigned char *decryptBuffer = new unsigned char[maxDecryptSize]; + + int decryptLength = RSA_private_decrypt(len, UnChar, + decryptBuffer, privateKey, RSA_PKCS1_PADDING); + if (decryptLength != -1) { + decryptedText.assign(reinterpret_cast(decryptBuffer), decryptLength); + } + + delete[] decryptBuffer; + return decryptedText; +} + +const char *dss::module::AssistLoginWork::keyToString(RSA *rsaKey, int isPublic) +{ + BIO *bio = BIO_new(BIO_s_mem()); + char *pemKey = NULL; + + if (isPublic) { + if (PEM_write_bio_RSAPublicKey(bio, rsaKey) != 1) { + printf("Error converting RSA public key to PEM.\n"); + BIO_free(bio); + return NULL; + } + } else { + if (PEM_write_bio_RSAPrivateKey(bio, rsaKey, NULL, NULL, 0, NULL, NULL) != 1) { + printf("Error converting RSA private key to PEM.\n"); + BIO_free(bio); + return NULL; + } + } + + int keyLength = BIO_pending(bio); + pemKey = (char *) malloc(keyLength + 1); + + if (pemKey == NULL) { + printf("Memory allocation error.\n"); + BIO_free(bio); + return NULL; + } + + if (BIO_read(bio, pemKey, keyLength) != keyLength) { + printf("Error reading PEM key from BIO.\n"); + free(pemKey); + pemKey = NULL; + } + + pemKey[keyLength] = '\0'; + BIO_free(bio); + return pemKey; +} + +void dss::module::AssistLoginWork::onStopService() +{ + if (m_socketHelper) { + delete m_socketHelper; + m_socketHelper = nullptr; + } +} + +void dss::module::AssistLoginWork::onStartService() +{ + if (m_socketHelper == nullptr) { + m_socketHelper = new SocketHelper(SocketServiceName); + connect(m_socketHelper, &SocketHelper::createPublicEncrypt, this, &AssistLoginWork::onCreatePublicEncrypt); + connect(m_socketHelper, &SocketHelper::createPrivateEncrypt, this, &AssistLoginWork::onCreatePrivateEncrypt); + connect(m_socketHelper, &SocketHelper::getAuthResult, this, &AssistLoginWork::onGetAuthResult); + connect(m_socketHelper, &SocketHelper::startAuth, this, &AssistLoginWork::onStartAuth); + } +} + +void dss::module::AssistLoginWork::onCreatePrivateEncrypt() +{ + if (m_socketHelper == nullptr) { + return; + } + const char * key = keyToString(m_keyPair, 0); + m_socketHelper->sendDataToClient(QByteArray(key)); + delete[] key; +} diff --git a/plugins/assist_login/assist_login_work.h b/plugins/assist_login/assist_login_work.h new file mode 100644 index 00000000..088e039d --- /dev/null +++ b/plugins/assist_login/assist_login_work.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ASSIST_LOGIN_WORK_H +#define ASSIST_LOGIN_WORK_H + +#include +#include +#include +#include + +#include "socketHelper.h" + +namespace dss { + +namespace module { + +class AssistLoginWork: public QObject +{ + Q_OBJECT +public: + explicit AssistLoginWork(QObject *parent = nullptr); + ~AssistLoginWork(); + +public Q_SLOTS: + void onCreatePublicEncrypt(); + void onCreatePrivateEncrypt(); + void onGetAuthResult(); + void onStartAuth(const QString &user, const QString &passwd); + void onStopService(); + void onStartService(); + +Q_SIGNALS: + void sendAuthToken(const QString &user, const QString &passwd); + +private: + void init(); + // 生成RSA密钥对 + void generateRSAKeyPair(); + // RSA加密 + std::string rsaEncrypt(const std::string &plaintext, RSA *publicKey); + // RSA解密 + std::string rsaDecrypt(const char *encryptedText, RSA *privateKey, int len); + // 将公钥转换为字符串 + const char *keyToString(RSA *rsaKey, int isPublic); + + SocketHelper *m_socketHelper; + RSA *m_keyPair; +}; + +} +} +#endif //ASSIST_LOGIN_WORK_H diff --git a/plugins/assist_login/interface/CMakeLists.txt b/plugins/assist_login/interface/CMakeLists.txt new file mode 100644 index 00000000..4035bd97 --- /dev/null +++ b/plugins/assist_login/interface/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.13) +project(assist_Login_interface) + +set(CMAKE_CXX_STANDARD 11) + +find_package(Qt5 COMPONENTS Network REQUIRED) +find_package(PkgConfig REQUIRED) + +pkg_check_modules(SSL REQUIRED IMPORTED_TARGET libcrypto libssl openssl) + +set(LIB_NAME assist_Login_interface) + + +# 添加动态库源文件 +add_library(${LIB_NAME} SHARED include/assist_login_interface.h src/assist_login_interface.cpp) + +target_link_libraries(${LIB_NAME} + Qt5::Network + ${Qt_LIBS} + PkgConfig::SSL) + +# 将包含目录添加到 mylib 目标中 +target_include_directories(${LIB_NAME} PUBLIC include) + +link_libraries( + +) + +# 安装/user/lib +install(FILES include/assist_login_interface.h DESTINATION /usr/include/dde-session-shell) +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/assist_login/interface/include/assist_login_interface.h b/plugins/assist_login/interface/include/assist_login_interface.h new file mode 100644 index 00000000..cd7be5f7 --- /dev/null +++ b/plugins/assist_login/interface/include/assist_login_interface.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ASSIST_LOGIN_INTERFACE_H +#define ASSIST_LOGIN_INTERFACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief 发送账号和密码进行登录认证 + * @param 本地账号账号名称,账号密码。 + * @return true表示发送认证成功,false发送认证失败,注意:该结果不代表认证结果 + */ +extern int sendAuth(const char *account, unsigned char *pw, int len); + +/** + * @brief 判断认证服务是否已经开启 + * @return true表示已经开启,false表示认证服务还未开启 + */ +extern int authServiceStarted(); + +/** + * @brief 获取非对称加密使用的公钥 + * @return 公钥token + */ +extern const char *getPublicEncrypt(); + +#ifdef __cplusplus +} +#endif + +#endif //ASSIST_LOGIN_INTERFACE_H diff --git a/plugins/assist_login/interface/src/assist_login_interface.cpp b/plugins/assist_login/interface/src/assist_login_interface.cpp new file mode 100644 index 00000000..0fed0ab1 --- /dev/null +++ b/plugins/assist_login/interface/src/assist_login_interface.cpp @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "assist_login_interface.h" +#include "QtNetwork/QLocalSocket" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + +const QString SocketServiceName = "dde-assist-login"; + +int sendAuth(const char *user, unsigned char *pw, int len) +{ + + EVP_cleanup(); + // 初始化OpenSSL库 + OpenSSL_add_all_algorithms(); + + QByteArray sendData = "\ngetPrivateEncrypt: \n"; + QLocalSocket socket; + socket.connectToServer(SocketServiceName); + if (!socket.waitForConnected()) { + return 0; + } + socket.write(sendData); + if (!socket.waitForBytesWritten()) { + socket.close(); + return 0; + } + if (!socket.waitForReadyRead()) { + return 0; + } + char *data = socket.readAll().data(); + // 使用私钥字符串创建RSA结构体指针 + RSA *rsa = NULL; + BIO *bio = NULL; + bio = BIO_new_mem_buf((void *) data, -1); + if (!PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL)) { + fprintf(stderr, "Error reading private key.\n"); + ERR_print_errors_fp(stderr); + return 1; + } + // 解密 + unsigned char decrypted[RSA_size(rsa)]; + + int decrypted_len = RSA_private_decrypt(len, pw, decrypted, rsa, RSA_PKCS1_PADDING); + if (decrypted_len == -1) { + fprintf(stderr, "Decryption failed.\n"); + ERR_print_errors_fp(stderr); + return 1; + } + + QByteArray users = QByteArray(user); + QByteArray password = QByteArray((char *) decrypted, len); + QByteArray sendData1 = "\nsendAuth:" + users + "," + password + "\n"; + + int account = socket.write(sendData1); + std::cout << account << std::endl; + if (!socket.waitForBytesWritten()) { + socket.close(); + return 0; + } + socket.close(); + return 1; +} + +int authServiceStarted() +{ + QLocalSocket socket; + socket.connectToServer(SocketServiceName); + if (socket.waitForConnected(500)) { + // Local server is running + socket.disconnectFromServer(); + return true; + } + // Local server is not running + return false; +} + +const char *getPublicEncrypt() +{ + QByteArray sendData = "\ngetPublicEncrypt: \n"; + QLocalSocket socket; + socket.connectToServer(SocketServiceName); + if (!socket.waitForConnected()) { + return ""; + } + socket.write(sendData); + if (!socket.waitForBytesWritten()) { + socket.close(); + return ""; + } + if (!socket.waitForReadyRead()) { + return ""; + } + QByteArray byteArray = socket.readAll().data(); + const char * data = new char[byteArray.count()]; + std::strcpy(const_cast(data), byteArray.data()); + socket.close(); + return data; +} + +} + diff --git a/plugins/assist_login/login.json b/plugins/assist_login/login.json new file mode 100644 index 00000000..d4cff3f4 --- /dev/null +++ b/plugins/assist_login/login.json @@ -0,0 +1,3 @@ +{ + "api": "1.2.0" +} diff --git a/plugins/assist_login/socketHelper.cpp b/plugins/assist_login/socketHelper.cpp new file mode 100644 index 00000000..cf9b5728 --- /dev/null +++ b/plugins/assist_login/socketHelper.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "socketHelper.h" + +namespace dss { +namespace module { + +static QMap s_FunMap = { + {"getPublicEncrypt", &SocketHelper::getPublicEncrypt}, + {"sendAuth", &SocketHelper::sendAuth}, + {"getCurrentUserAuthResult", &SocketHelper::getCurrentUserAuthResult}, + {"getPrivateEncrypt", &SocketHelper::getPrivateEncrypt} +}; + +SocketHelper::SocketHelper(QString ServiceName, QObject *parent) + : QObject(parent) + , m_server(nullptr) + , m_serverName(ServiceName) + , m_lastData("") +{ + initService(); +} + +SocketHelper::~SocketHelper() +{ + if (m_server) { + delete m_server; + } +} + +void SocketHelper::initService() +{ + if (m_server) { + return; + } + + m_server = new QLocalServer(this); + connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnectionHandler())); + m_server->setSocketOptions(QLocalServer::WorldAccessOption); + + m_server->removeServer(m_serverName); + bool islisten = m_server->listen(m_serverName); + if (!islisten) { + islisten = m_server->listen(m_serverName); + } +} + +void SocketHelper::newConnectionHandler() +{ + QLocalSocket *socket = m_server->nextPendingConnection(); + connect(socket, SIGNAL(readyRead()), this, SLOT(readyReadHandler())); + connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedHandler())); + m_clients.append(socket); +} + +void SocketHelper::disconnectedHandler() +{ + QLocalSocket *socket = static_cast(sender()); + if (socket) { + m_clients.removeAll(socket); + socket->deleteLater(); + } +} + +void SocketHelper::readyReadHandler() +{ + QLocalSocket *socket = qobject_cast(sender()); + if (!socket) { + return; + } + + QByteArray allData = socket->readAll(); + allData = m_lastData + allData; + QList dataArray = allData.split('\n'); + m_lastData = dataArray.last(); + for (const QByteArray &data : dataArray) { + int keyIndex = data.indexOf(':'); + if (keyIndex != -1) { + QString key = data.left(keyIndex); + QByteArray value = data.mid(keyIndex + 1); + if (s_FunMap.contains(key)) { + (this->*s_FunMap.value(key))(socket, value); + } + } + } + +} + +void SocketHelper::getPublicEncrypt(QLocalSocket *socket, const QByteArray &data) +{ + Q_EMIT createPublicEncrypt(); + socket->write("\nreceive:" + data + "\n"); +} + +void SocketHelper::sendAuth(QLocalSocket *socket, const QByteArray &data) +{ + QList value = data.split(','); + if (data.count() > 1) { + QString user = QString(value[0]); + QString pwd = QString(value[1]); + Q_EMIT startAuth(user, pwd); + } + socket->write("\nreceive:" + data + "\n"); +} + +void SocketHelper::getCurrentUserAuthResult(QLocalSocket *socket, const QByteArray &data) +{ + Q_UNUSED(data); + socket->write("\nreceive:" + data + "\n"); +} + +void SocketHelper::sendDataToClient(const QByteArray &data) +{ + for (auto it = m_clients.begin(); it != m_clients.end(); it++) { + (*it)->write(data); + } +} + +void SocketHelper::getPrivateEncrypt(QLocalSocket *socket, const QByteArray &data) +{ + Q_EMIT createPrivateEncrypt(); + socket->write("\nreceive:" + data + "\n"); +} +} +} diff --git a/plugins/assist_login/socketHelper.h b/plugins/assist_login/socketHelper.h new file mode 100644 index 00000000..286c2a4e --- /dev/null +++ b/plugins/assist_login/socketHelper.h @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef SOCKETHELPER_H +#define SOCKETHELPER_H + +#include "QObject" +#include "QtNetwork/QLocalSocket" +#include "QtNetwork/QLocalServer" + +namespace dss { + +namespace module { + +class SocketHelper: public QObject +{ + Q_OBJECT +public: + explicit SocketHelper(QString ServiceName, QObject *parent = Q_NULLPTR); + ~SocketHelper(); + + void getPublicEncrypt(QLocalSocket *socket, const QByteArray &data); + void getPrivateEncrypt(QLocalSocket *socket, const QByteArray &data); + void sendAuth(QLocalSocket *socket, const QByteArray &data); + void getCurrentUserAuthResult(QLocalSocket *socket, const QByteArray &data); + void sendDataToClient(const QByteArray &data); + +Q_SIGNALS: + void createPublicEncrypt(); + void createPrivateEncrypt(); + void getAuthResult(); + void startAuth(const QString &user, const QString &passwd); + +private Q_SLOTS: + void newConnectionHandler(); + void readyReadHandler(); + void disconnectedHandler(); + +private: + void initService(); + + QLocalServer *m_server; + QList m_clients; + QString m_serverName; + QByteArray m_lastData; +}; + +} +} + +#endif //SOCKETHELPER_H diff --git a/plugins/examples/CMakeLists.txt b/plugins/examples/CMakeLists.txt new file mode 100644 index 00000000..27149701 --- /dev/null +++ b/plugins/examples/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(login-plugins/login-basic) +add_subdirectory(login-plugins/login-complex) +add_subdirectory(login-plugins/login-fullManaged) +add_subdirectory(login-plugins/login-udcp) +add_subdirectory(tray-plugins/network) +#add_subdirectory(tray-plugins/webview) diff --git a/plugins/examples/login-plugins/login-basic/CMakeLists.txt b/plugins/examples/login-plugins/login-basic/CMakeLists.txt new file mode 100644 index 00000000..65c1e5dc --- /dev/null +++ b/plugins/examples/login-plugins/login-basic/CMakeLists.txt @@ -0,0 +1,84 @@ +# 设置运行此配置所需的 cmake 的最低版本 +cmake_minimum_required(VERSION 3.11) + +# 使用 set 命令设置一个变量 +set(PLUGIN_NAME login-basic) + +# 设置项目名称 +project(${PLUGIN_NAME}) + +# 启用 qt moc 的支持 +set(CMAKE_AUTOMOC ON) +# 启用 qrc 资源文件的支持 +set(CMAKE_AUTORCC ON) + +find_package(Qt6 COMPONENTS Core QUIET) +if (Qt6_FOUND) + set(QT_VERSION_MAJOR 6) + set(DTK_VERSION_MAJOR 6) +else () + set(QT_VERSION_MAJOR 5) + set(DTK_VERSION_MAJOR 5) +endif () + +# 指定所有源码文件 +# 使用了 cmake 的 file 命令,递归查找项目目录下所有头文件和源码文件 +# 并将结果放入 SRCS 变量中,方便后续取用 +file(GLOB_RECURSE SRCS "*.h" "*.cpp") + +# 指定要用到的库 +# 使用了 cmake 的 find_package 命令,查找库 Qt对应版本的模块,如Widgets等, +# REQUIRED 参数表示如果没有找到则报错 +# find_package 命令在找到并加载指定的库之后会设置一些变量 +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) +find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED COMPONENTS Widget) +find_package(DdeSessionShell REQUIRED) + +# find_package 命令还可以用来加载 cmake 的功能模块 +# 并不是所有的库都直接支持 cmake 查找的,但大部分都支持了 pkg-config 这个标准, +# 因此 cmake 提供了间接加载库的模块:FindPkgConfig, 下面这行命令表示加载 FindPkgConfig 模块, +# 这个 cmake 模块提供了额外的基于 “pkg-config” 加载库的能力 +# 执行下面的命令后后会设置如下变量,不过一般用不到: +# PKG_CONFIG_FOUND pkg-config 可执行文件是否找到了 +# PKG_CONFIG_EXECUTABLE pkg-config 可执行文件的路径 +# PKG_CONFIG_VERSION_STRING pkg-config 的版本信息 +find_package(PkgConfig REQUIRED) + +# add_definitions 命令用于声明/定义一些编译/预处理参数 +add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN") + +# 新增一个编译目标 +# 这里使用命令 add_library 来表示本项目要生成一个库文件目标, +# 类似的还有命令 add_executable 添加一个可执行二进制目标,甚至 add_custom_target(使用较少) 添加自定义目标 +# SHARED 表示生成的库应该是动态库, +# 变量 ${PLUGIN_NAME} 和 ${SRCS} 都是前面处理好的, +# 另外 qrc 资源文件也应该追加在后面以编译进目标中。 +add_library(${PLUGIN_NAME} SHARED ${SRCS}) + +# 设置目标的生成位置,这里表示生成在执行 make 的目录, +# 另外还有很多可用于设置的属性,可查阅 cmake 文档。 +set_target_properties(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ./) + +# 设置目标要使用的 include 目录,即头文件目录 +# 变量 ${DtkWidget_INCLUDE_DIRS} 是在前面执行 find_package 命令时引入的 +# 当出现编译失败提示找不到某些库的头文件时应该检查此处是否将所有需要的头文件都包含了 +target_include_directories(${PLUGIN_NAME} PUBLIC + Qt${QT_VERSION_MAJOR}::Widgets + ${DtkWidget_INCLUDE_DIRS} + ${DdeSessionShell_INCLUDE_DIRS} +) + +# 设置目标要使用的链接库 +# 变量 Dtk${DTK_VERSION_MAJOR}::Widget 和 Qt${QT_VERSION_MAJOR}::Widgets 是在前面执行 find_package 命令时引入的 +# 当出现运行时错误提示某些符号没有定义时应该检查此处是否将所有用的库都写在了这里 +target_link_libraries(${PLUGIN_NAME} PRIVATE + Qt${QT_VERSION_MAJOR}::Widgets + Dtk${DTK_VERSION_MAJOR}::Widget + ${DdeSessionShell_LIBRARIES} +) + +# 设置安装路径的前缀(默认为"/usr/local") +set(CMAKE_INSTALL_PREFIX "/usr") + +# 设置执行 make install 时哪个目标应该被 install 到哪个位置 +install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/examples/login-plugins/login-basic/login.json b/plugins/examples/login-plugins/login-basic/login.json new file mode 100644 index 00000000..95156e4b --- /dev/null +++ b/plugins/examples/login-plugins/login-basic/login.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Login" +} diff --git a/plugins/examples/login-plugins/login-basic/login_module.cpp b/plugins/examples/login-plugins/login-basic/login_module.cpp new file mode 100644 index 00000000..72fb39f6 --- /dev/null +++ b/plugins/examples/login-plugins/login-basic/login_module.cpp @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login_module.h" + +#include +#include +#include +#include +#include +#include + +namespace dss { +namespace module_v2 { + +LoginModule::LoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_loginWidget(nullptr) +{ + setObjectName(QStringLiteral("basic-login-plugin")); +} + +LoginModule::~LoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget; + m_loginWidget = nullptr; + } +} + +void LoginModule::init() +{ + initUI(); +} + +void LoginModule::reset() +{ + init(); +} + +void LoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void LoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void LoginModule::initUI() +{ + if (m_loginWidget) { + return; + } + m_loginWidget = new QWidget; + m_loginWidget->setAccessibleName(QStringLiteral("LoginWidget")); + m_loginWidget->setMinimumSize(260, 100); + + m_loginWidget->setLayout(new QHBoxLayout); + QPushButton *passButton = new QPushButton("Validation passed", m_loginWidget); + passButton->setFixedSize(160, 40); + m_loginWidget->layout()->addWidget(passButton); + + connect(passButton, &QPushButton::clicked, this, [this] { + AuthCallbackData data; + data.account = "uos"; + data.token = "1"; + data.result = AuthResult::Success; + m_authCallback(&data, m_appData); + }, Qt::DirectConnection); +} + +} // namespace module +} // namespace dss diff --git a/plugins/examples/login-plugins/login-basic/login_module.h b/plugins/examples/login-plugins/login-basic/login_module.h new file mode 100644 index 00000000..20890e0c --- /dev/null +++ b/plugins/examples/login-plugins/login-basic/login_module.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGIN_MODULE_H +#define LOGIN_MODULE_H + +#include "login_module_interface_v2.h" + +namespace dss { +namespace module_v2 { + +class LoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + +public: + explicit LoginModule(QObject *parent = nullptr); + ~LoginModule() override; + + void init() override; + + inline QString key() const override { return objectName(); } + inline QWidget *content() override { return m_loginWidget; } + void reset() override; + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + +private: + void initUI(); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + QWidget *m_loginWidget; +}; + +} // namespace module_v2 +} // namespace dss +#endif // LOGIN_MODULE_H diff --git a/modules/examples/login/CMakeLists.txt b/plugins/examples/login-plugins/login-complex/CMakeLists.txt similarity index 69% rename from modules/examples/login/CMakeLists.txt rename to plugins/examples/login-plugins/login-complex/CMakeLists.txt index 572feafb..5edcf612 100644 --- a/modules/examples/login/CMakeLists.txt +++ b/plugins/examples/login-plugins/login-complex/CMakeLists.txt @@ -1,5 +1,4 @@ include_directories( - ${DFrameworkDBus_INCLUDE_DIRS} global ) @@ -7,12 +6,10 @@ link_libraries( ${Qt_LIBS} ) -set(LIB_NAME login) +set(LIB_NAME login-complex) aux_source_directory(. SRCS) -# add_library(${LIB_NAME} STATIC ${SRCS}) - add_library(${LIB_NAME} SHARED ${SRCS}) install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/examples/login-plugins/login-complex/login-widget.cpp b/plugins/examples/login-plugins/login-complex/login-widget.cpp new file mode 100644 index 00000000..1c4af5d7 --- /dev/null +++ b/plugins/examples/login-plugins/login-complex/login-widget.cpp @@ -0,0 +1,119 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login-widget.h" + +#include +#include +#include +#include +#include + +LoginWidget::LoginWidget(QWidget *parent) + : QWidget(parent) + , m_messageLabel(nullptr) +{ + setObjectName(QStringLiteral("LoginWidget")); + setAccessibleName(QStringLiteral("LoginWidget")); + + init(); +} + +void LoginWidget::init() +{ + // init ui + QLabel *userNameLabel = new QLabel("User Name: ", this); + userNameLabel->setFixedHeight(35); + QLineEdit *userNameEdit = new QLineEdit(this); + userNameEdit->setFixedHeight(35); + QHBoxLayout *userNameLayout = new QHBoxLayout(); + userNameLayout->addWidget(userNameLabel, 3, Qt::AlignRight); + userNameLayout->addSpacing(15); + userNameLayout->addWidget(userNameEdit, 7); + setFocusProxy(userNameEdit); + + QLabel *tokenLabel = new QLabel("Token: ", this); + tokenLabel->setFixedHeight(35); + QLineEdit *tokenEdit = new QLineEdit(this); + tokenEdit->setFixedHeight(35); + QHBoxLayout *tokenLayout = new QHBoxLayout(); + tokenLayout->addWidget(tokenLabel, 3, Qt::AlignRight); + tokenLayout->addSpacing(15); + tokenLayout->addWidget(tokenEdit, 7); + + m_messageLabel = new QLabel(this); + m_messageLabel->setMinimumHeight(80); + m_messageLabel->setWordWrap(true); + QFont font = m_messageLabel->font(); + font.setPixelSize(30); + m_messageLabel->setFont(font); + m_messageLabel->setAlignment(Qt::AlignCenter); + + QPushButton *sendButton = new QPushButton("Send Token", this); + sendButton->setFixedSize(120, 35); + sendButton->setEnabled(false); + sendButton->setDefault(true); + + QVBoxLayout* layout = new QVBoxLayout(this); + setLayout(layout); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + layout->setContentsMargins(15, 15, 15, 15); +#else + layout->setMargin(15); +#endif + layout->addLayout(userNameLayout); + layout->addSpacing(30); + layout->addLayout(tokenLayout); + layout->addSpacing(50); + layout->addWidget(m_messageLabel); + layout->addStretch(1); + layout->addWidget(sendButton, 0, Qt::AlignCenter); + layout->addSpacing(35); + + // init connections + auto setButtonEnabledFunc = [sendButton, userNameEdit, tokenEdit] { + const QString &userName = userNameEdit->text().trimmed(); + const QString &token = tokenEdit->text().trimmed(); + sendButton->setEnabled(!userName.isEmpty() && !token.isEmpty()); + }; + + auto sendToken = [this, userNameEdit, tokenEdit] { + const QString &userName = userNameEdit->text().trimmed(); + const QString &token = tokenEdit->text().trimmed(); + + Q_EMIT sendAuthToken(userName, token); + }; + + connect(userNameEdit, &QLineEdit::textChanged, setButtonEnabledFunc); + connect(tokenEdit, &QLineEdit::textChanged, setButtonEnabledFunc); + + connect(sendButton, &QPushButton::clicked, this, sendToken); + connect(tokenEdit, &QLineEdit::returnPressed, this, sendToken); + connect(userNameEdit, &QLineEdit::returnPressed, this, [this, userNameEdit, tokenEdit, sendToken] { + if (!userNameEdit->text().trimmed().isEmpty()) { + if (!tokenEdit->text().trimmed().isEmpty()) { + sendToken(); + } else { + tokenEdit->setFocus(); + } + } + }); + + connect(this, &LoginWidget::reset, this, [sendButton, userNameEdit, tokenEdit, this] { + userNameEdit->clear(); + tokenEdit->clear(); + sendButton->setEnabled(false); + m_messageLabel->clear(); + }); +} + +void LoginWidget::showMessage(const QString &message) +{ + m_messageLabel->setText(message); +} + +void LoginWidget::hideMessage() +{ + m_messageLabel->clear(); +} diff --git a/plugins/examples/login-plugins/login-complex/login-widget.h b/plugins/examples/login-plugins/login-complex/login-widget.h new file mode 100644 index 00000000..10f90299 --- /dev/null +++ b/plugins/examples/login-plugins/login-complex/login-widget.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef __LOGIN_WIDGET__H__ +#define __LOGIN_WIDGET__H__ + +#include + +class QLabel; + +class LoginWidget : public QWidget +{ + Q_OBJECT +public: + explicit LoginWidget(QWidget *parent = nullptr); + + void showMessage(const QString &message); + void hideMessage(); + +private: + void init(); + +Q_SIGNALS: + void sendAuthToken(const QString &account, const QString &token); + void reset(); + +private: + QLabel *m_messageLabel; +}; + +#endif //!__LOGIN_WIDGET__H__ \ No newline at end of file diff --git a/plugins/examples/login-plugins/login-complex/login.json b/plugins/examples/login-plugins/login-complex/login.json new file mode 100644 index 00000000..95156e4b --- /dev/null +++ b/plugins/examples/login-plugins/login-complex/login.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Login" +} diff --git a/plugins/examples/login-plugins/login-complex/login_module.cpp b/plugins/examples/login-plugins/login-complex/login_module.cpp new file mode 100644 index 00000000..d9c7b6af --- /dev/null +++ b/plugins/examples/login-plugins/login-complex/login_module.cpp @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login_module.h" + +#include +#include +#include +#include +#include +#include + +namespace dss { +namespace module_v2 { + +LoginModule::LoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_messageCallback(nullptr) + , m_loginWidget(nullptr) + , m_appType(AppType::Lock) +{ + setObjectName(QStringLiteral("complex-login-plugin")); +} + +LoginModule::~LoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget; + } +} + +void LoginModule::init() +{ + initUI(); + updateInfo(); +} + +void LoginModule::reset() +{ + init(); +} + +void LoginModule::initUI() +{ + if (m_loginWidget) { + emit m_loginWidget->reset(); + return; + } + + m_loginWidget = new LoginWidget(); + m_loginWidget->setFixedSize(362, 420); + QObject::connect(m_loginWidget, &LoginWidget::sendAuthToken, this, [this](const QString &account, const QString &token) { +#if 0 + // 通常需要判断一下登录器当前的用户和插件正在验证的用户是否相同,具体根据需求而定。 + if (m_userName != account && m_userName != "...") { + qDebug() << "User name mismatch, user name: " << m_userName; + m_loginWidget->showMessage("The user name does not match the current user, please check and re verify"); + return; + } +#endif + qDebug() << "Send auth token: " << account; + AuthCallbackData data; + data.account = account; + data.token = token; + data.result = 1; + m_authCallback(&data, m_appData); + }, Qt::DirectConnection); +} + +void LoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void LoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void LoginModule::setMessageCallback(MessageCallbackFunc messageCallback) +{ + m_messageCallback = messageCallback; +} + +void LoginModule::updateInfo() +{ + if (!m_messageCallback) { + qWarning() << "message callback func is nullptr"; + return; + } + + // 发送获取属性的请求 + QJsonObject message; + message.insert("CmdType", "GetProperties"); + QJsonArray array; + array.append("AppType"); + array.append("CurrentUser"); + message["Data"] = array; + QJsonDocument doc; + doc.setObject(message); + QString ret = m_messageCallback(doc.toJson(), m_appData); + + // 解析返回值 + QJsonParseError jsonParseError; + const QJsonDocument retDoc = QJsonDocument::fromJson(ret.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || retDoc.isEmpty()) { + qWarning() << "Failed to analysis AppType info from shell!: " << ret; + return ; + } + + QJsonObject obj = retDoc.object(); + if (obj.value("Code").toInt() != 0) { + qWarning() << "Get properties failed, message: " << obj.value("Message").toString(); + return; + } + + QJsonObject data = obj.value("Data").toObject(); + if (data.contains("AppType")) { + m_appType = data.value("AppType").toInt(); + qInfo() << "App type: " << m_appType; + } + + if (data.contains("CurrentUser")) { + QJsonObject user = data.value("CurrentUser").toObject(); + m_userName = user.value("Name").toString(); + qInfo() << "Current user: " << user; + } +} + +QString LoginModule::message(const QString &message) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + qWarning() << "Failed to obtain message from shell!: " << message; + return ""; + } + + QJsonObject retObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + + QJsonObject msgObj = messageDoc.object(); + QString cmdType = msgObj.value("CmdType").toString(); + QJsonObject data = msgObj.value("Data").toObject(); + qInfo() << "Cmd type: " << cmdType; + if (cmdType == "CurrentUserChanged") { + m_userName = data.value("Name").toString(); + qDebug() << "Current user changed, user name: " << m_userName; + } else if (cmdType == "GetConfigs") { + QJsonObject retDataObj; + retDataObj["ShowAvatar"] = true; + retDataObj["ShowUserName"] = true; + retDataObj["ShowSwitchButton"] = true; + retDataObj["ShowLockButton"] = false; + retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::Default; + retDataObj["DisableOtherAuthentications"] = true; + retObj["Data"] = retDataObj; + } else if (cmdType == "AuthState") { + int authType = data.value("AuthType").toInt(); + int authState = data.value("AuthState").toInt(); + // 所有类型验证成功,重置插件状态 + if (authType == AuthType::AT_All && authState == AuthState::AS_Success) { + init(); + } + } + + QJsonDocument doc; + doc.setObject(retObj); + return doc.toJson(); +} + +} // namespace module +} // namespace dss diff --git a/plugins/examples/login-plugins/login-complex/login_module.h b/plugins/examples/login-plugins/login-complex/login_module.h new file mode 100644 index 00000000..3effe60c --- /dev/null +++ b/plugins/examples/login-plugins/login-complex/login_module.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGIN_MODULE_H +#define LOGIN_MODULE_H + +#include "login_module_interface_v2.h" +#include "login-widget.h" + +namespace dss { +namespace module_v2 { + +class LoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + +public: + + enum DefaultAuthLevel { + NoDefault = 0, + Default, + StrongDefault + }; + + explicit LoginModule(QObject *parent = nullptr); + ~LoginModule() override; + + void init() override; + inline QString key() const override { return objectName(); } + inline QWidget *content() override { return m_loginWidget; } + inline QString icon() const override { return "code-block"; } + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + void setMessageCallback(MessageCallbackFunc) override; + QString message(const QString&) override; + void reset() override; + +private: + void initUI(); + void updateInfo(); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + MessageCallbackFunc m_messageCallback; + LoginWidget *m_loginWidget; + QString m_userName; + int m_appType; +}; + +} // namespace module_v2 +} // namespace dss +#endif // LOGIN_MODULE_H diff --git a/plugins/examples/login-plugins/login-fullManaged/CMakeLists.txt b/plugins/examples/login-plugins/login-fullManaged/CMakeLists.txt new file mode 100644 index 00000000..bba76f7a --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/CMakeLists.txt @@ -0,0 +1,15 @@ +include_directories( + global +) + +link_libraries( + ${Qt_LIBS} +) + +set(LIB_NAME login-FullManaged) + +aux_source_directory(. SRCS) + +add_library(${LIB_NAME} SHARED ${SRCS}) + +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.cpp b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.cpp new file mode 100644 index 00000000..fc67858a --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.cpp @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "full_managed_login_module.h" + +#include +#include +#include +#include +#include +#include + +namespace dss { +namespace module_v2 { + +FullManagedLoginModule::FullManagedLoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_messageCallback(nullptr) + , m_loginWidget(nullptr) + , m_appType(AppType::Lock) + , m_isActive(true) +{ + setObjectName(QStringLiteral("FullManagedLoginModule")); +} + +FullManagedLoginModule::~FullManagedLoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget; + } +} + +void FullManagedLoginModule::init() +{ + initUI(); + updateInfo(); +} + +void FullManagedLoginModule::reset() +{ + init(); +} + +void FullManagedLoginModule::initUI() +{ + if (m_loginWidget) { + emit m_loginWidget->reset(); + return; + } + + m_loginWidget = new FullManagedLoginWidget(); + m_loginWidget->setFixedSize(362, 420); + QObject::connect(m_loginWidget, &FullManagedLoginWidget::sendAuthToken, this, [this](const QString &account, const QString &token) { + if (QApplication::applicationName().contains("lock")) { + if (m_userName != account && m_userName != "...") { + qDebug() << "User name mismatch, user name: " << m_userName; + m_loginWidget->showMessage("The user name does not match the current user, please check and re verify"); + return; + } + } + + qDebug() << "send Auth Token: " << account; + AuthCallbackData data; + data.account = account; + data.token = token; + data.result = 1; + m_authCallback(&data, m_appData); + }, + Qt::DirectConnection); + + connect(m_loginWidget, &FullManagedLoginWidget::deactived, this, [this] { + m_isActive = false; + QTimer::singleShot(DEACTIVE_TIME_INTERVAL, this, [this] { + m_isActive = true; + }); + }); +} + +void FullManagedLoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void FullManagedLoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void FullManagedLoginModule::setMessageCallback(MessageCallbackFunc messageCallback) +{ + m_messageCallback = messageCallback; +} + +void FullManagedLoginModule::updateInfo() +{ + if (!m_messageCallback) { + qWarning() << "message callback func is nullptr"; + return; + } + + // 发送获取属性的请求 + QJsonObject message; + message.insert("CmdType", "GetProperties"); + QJsonArray array; + array.append("AppType"); + array.append("CurrentUser"); + message["Data"] = array; + QJsonDocument doc; + doc.setObject(message); + QString ret = m_messageCallback(doc.toJson(), m_appData); + + // 解析返回值 + QJsonParseError jsonParseError; + const QJsonDocument retDoc = QJsonDocument::fromJson(ret.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || retDoc.isEmpty()) { + qWarning() << "Failed to analysis AppType info from shell!: " << ret; + return; + } + + QJsonObject obj = retDoc.object(); + if (obj.value("Code").toInt() != 0) { + qWarning() << "Get properties failed, message: " << obj.value("Message").toString(); + return; + } + + QJsonObject data = obj.value("Data").toObject(); + if (data.contains("AppType")) { + m_appType = data.value("AppType").toInt(); + qInfo() << "App type: " << m_appType; + } + + if (data.contains("CurrentUser")) { + QJsonObject user = data.value("CurrentUser").toObject(); + m_userName = user.value("Name").toString(); + qInfo() << "Current user: " << user; + } +} + +QString FullManagedLoginModule::message(const QString &message) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + qWarning() << "Failed to obtain message from shell!: " << message; + return ""; + } + + QJsonObject retObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + + QJsonObject msgObj = messageDoc.object(); + QString cmdType = msgObj.value("CmdType").toString(); + QJsonObject data = msgObj.value("Data").toObject(); + qInfo() << "Cmd type: " << cmdType; + if (cmdType == "CurrentUserChanged") { + m_userName = data.value("Name").toString(); + qDebug() << "Current user changed, user name: " << m_userName; + } else if (cmdType == "GetConfigs") { + QJsonObject retDataObj; + retDataObj["ShowAvatar"] = false; + retDataObj["ShowUserName"] = false; + retDataObj["ShowSwitchButton"] = false; + retDataObj["ShowLockButton"] = false; + retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::Default; + retDataObj["AuthType"] = AuthType::AT_Custom; + retObj["Data"] = retDataObj; + } else if (cmdType == "AuthState") { + int authType = data.value("AuthType").toInt(); + int authState = data.value("AuthState").toInt(); + // 所有类型验证成功,重置插件状态 + if (authType == AuthType::AT_All && authState == AuthState::AS_Success) { + init(); + } + } else if (cmdType == "StartAuth") { + Q_EMIT m_loginWidget->greeterAuthStarted(); + } else if (cmdType == "IsPluginEnabled") { + QJsonObject retDataObj; + retDataObj["IsPluginEnabled"] = m_isActive; + retObj["Data"] = retDataObj; + } + + QJsonDocument doc; + doc.setObject(retObj); + return doc.toJson(); +} + +} // namespace module_v2 +} // namespace dss diff --git a/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.h b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.h new file mode 100644 index 00000000..494ead64 --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_module.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef FULL_MANAGED_LOGIN_MODULE_H +#define FULL_MANAGED_LOGIN_MODULE_H + +#include "login_module_interface_v2.h" +#include "full_managed_login_widget.h" + +namespace dss { +namespace module_v2 { + +class FullManagedLoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + +public: + enum DefaultAuthLevel { + NoDefault = 0, + Default, + StrongDefault + }; + + explicit FullManagedLoginModule(QObject *parent = nullptr); + ~FullManagedLoginModule() override; + + void init() override; + virtual ModuleType type() const override { return FullManagedLoginType; } + inline QString key() const override { return objectName(); } + inline QWidget *content() override { return m_loginWidget; } + inline QString icon() const override { return "code-block"; } + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + void setMessageCallback(MessageCallbackFunc) override; + QString message(const QString &) override; + void reset() override; + +private: + void initUI(); + void updateInfo(); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + MessageCallbackFunc m_messageCallback; + FullManagedLoginWidget *m_loginWidget; + QString m_userName; + int m_appType; + bool m_isActive; +}; + +} // namespace module_v2 +} // namespace dss +#endif // FULL_MANAGED_LOGIN_MODULE_H diff --git a/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.cpp b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.cpp new file mode 100644 index 00000000..976de61d --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.cpp @@ -0,0 +1,152 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "full_managed_login_widget.h" + +#include +#include +#include + +FullManagedLoginWidget::FullManagedLoginWidget(QWidget *parent) + : QWidget(parent) + , m_messageLabel(nullptr) + , m_userNameLabel(nullptr) + , m_userNameEdit(nullptr) + , m_tokenLabel(nullptr) + , m_tokenEdit(nullptr) + , m_sendButton(nullptr) + , m_disMissButton(nullptr) +{ + setObjectName(QStringLiteral("LoginWidget")); + setAccessibleName(QStringLiteral("LoginWidget")); + + initUI(); + initConnection(); +} + +void FullManagedLoginWidget::initUI() +{ + // init ui + m_userNameLabel = new QLabel("User Name: ", this); + m_userNameLabel->setFixedHeight(35); + + m_userNameEdit = new QLineEdit(this); + m_userNameEdit->setFixedHeight(35); + + QHBoxLayout *m_userNameLayout = new QHBoxLayout(); + m_userNameLayout->addWidget(m_userNameLabel, 3, Qt::AlignRight); + m_userNameLayout->addSpacing(15); + m_userNameLayout->addWidget(m_userNameEdit, 7); + setFocusProxy(m_userNameEdit); + + m_tokenLabel = new QLabel("Token: ", this); + m_tokenLabel->setFixedHeight(35); + + m_tokenEdit = new QLineEdit(this); + m_tokenEdit->setFixedHeight(35); + + QHBoxLayout *tokenLayout = new QHBoxLayout(); + tokenLayout->addWidget(m_tokenLabel, 3, Qt::AlignRight); + tokenLayout->addSpacing(15); + tokenLayout->addWidget(m_tokenEdit, 7); + + m_messageLabel = new QLabel(this); + m_messageLabel->setMinimumHeight(80); + m_messageLabel->setWordWrap(true); + QFont font = m_messageLabel->font(); + font.setPixelSize(30); + m_messageLabel->setFont(font); + m_messageLabel->setAlignment(Qt::AlignCenter); + + m_sendButton = new QPushButton("Send Token", this); + m_sendButton->setFixedSize(120, 35); + m_sendButton->setEnabled(false); + m_sendButton->setDefault(true); + + m_disMissButton = new QPushButton("deactive", this); + m_disMissButton->setFixedSize(120, 35); + m_disMissButton->setEnabled(true); + m_disMissButton->setDefault(true); + + QVBoxLayout *m_layout = new QVBoxLayout(this); + setLayout(m_layout); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_layout->setContentsMargins(15, 15, 15, 15); +#else + m_layout->setMargin(15); +#endif + m_layout->addLayout(m_userNameLayout); + m_layout->addSpacing(30); + m_layout->addLayout(tokenLayout); + m_layout->addSpacing(50); + m_layout->addWidget(m_messageLabel); + m_layout->addStretch(1); + m_layout->addWidget(m_sendButton, 0, Qt::AlignCenter); + m_layout->addWidget(m_disMissButton, 0, Qt::AlignCenter); + m_layout->addSpacing(15); +} + +void FullManagedLoginWidget::initConnection() +{ + // init connections + auto setButtonEnabledFunc = [this] { + const QString &userName = m_userNameEdit->text().trimmed(); + const QString &token = m_tokenEdit->text().trimmed(); + m_sendButton->setEnabled(!userName.isEmpty() && !token.isEmpty()); + }; + + auto sendTokenFunc = [this] { + const QString &userName = m_userNameEdit->text().trimmed(); + const QString &token = m_tokenEdit->text().trimmed(); + if (!userName.isEmpty() && !token.isEmpty()) { + Q_EMIT sendAuthToken(userName, token); + } + }; + + connect(m_userNameEdit, &QLineEdit::textChanged, setButtonEnabledFunc); + connect(m_tokenEdit, &QLineEdit::textChanged, setButtonEnabledFunc); + + connect(m_sendButton, &QPushButton::clicked, this, sendTokenFunc); + connect(this, &FullManagedLoginWidget::greeterAuthStarted, this, sendTokenFunc); + + connect(m_disMissButton, &QPushButton::clicked, this, [this] { + Q_EMIT deactived(); + m_disMissButton->setDisabled(true); + QTimer::singleShot(DEACTIVE_TIME_INTERVAL, this, [this] { + m_disMissButton->setDisabled(false); + }); + }); + + connect(m_tokenEdit, &QLineEdit::returnPressed, this, sendTokenFunc); + connect(m_userNameEdit, &QLineEdit::returnPressed, this, [this] { + if (!m_userNameEdit->text().trimmed().isEmpty()) { + if (!m_tokenEdit->text().trimmed().isEmpty()) { + const QString &userName = m_userNameEdit->text().trimmed(); + const QString &token = m_tokenEdit->text().trimmed(); + + Q_EMIT sendAuthToken(userName, token); + } else { + m_tokenEdit->setFocus(); + } + } + }); + + connect(this, &FullManagedLoginWidget::reset, this, [this] { + m_userNameEdit->clear(); + m_tokenEdit->clear(); + m_sendButton->setEnabled(false); + m_messageLabel->clear(); + }); +} + +void FullManagedLoginWidget::showMessage(const QString &message) +{ + m_messageLabel->setText(message); +} + +void FullManagedLoginWidget::hideMessage() +{ + m_messageLabel->clear(); +} diff --git a/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.h b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.h new file mode 100644 index 00000000..07547537 --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/full_managed_login_widget.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef __FULL_MANAGED_LOGIN_WIDGET__H__ +#define __FULL_MANAGED_LOGIN_WIDGET__H__ + +#include +#include +#include +#include + +// when this plugin example set to deactive, it would automaticaly reset active after time interval below +#define DEACTIVE_TIME_INTERVAL 30000 + +class QLabel; + +class FullManagedLoginWidget : public QWidget +{ + Q_OBJECT +public: + explicit FullManagedLoginWidget(QWidget *parent = nullptr); + + void showMessage(const QString &message); + void hideMessage(); + +private: + void initUI(); + void initConnection(); + +Q_SIGNALS: + void sendAuthToken(const QString &account, const QString &token); + void reset(); + void deactived(); + void greeterAuthStarted(); + +private: + QLabel *m_messageLabel; + QLabel *m_userNameLabel; + QLineEdit *m_userNameEdit; + QLabel *m_tokenLabel; + QLineEdit *m_tokenEdit; + QPushButton *m_sendButton; + QPushButton *m_disMissButton; +}; + +#endif //!__FULL_MANAGED_LOGIN_WIDGET__H__ diff --git a/plugins/examples/login-plugins/login-fullManaged/login.json b/plugins/examples/login-plugins/login-fullManaged/login.json new file mode 100644 index 00000000..bec81f0d --- /dev/null +++ b/plugins/examples/login-plugins/login-fullManaged/login.json @@ -0,0 +1,3 @@ +{ + "api": "2.0.0" +} diff --git a/plugins/examples/login-plugins/login-udcp/CMakeLists.txt b/plugins/examples/login-plugins/login-udcp/CMakeLists.txt new file mode 100644 index 00000000..bdbc6f3f --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/CMakeLists.txt @@ -0,0 +1,15 @@ +include_directories( + global +) + +link_libraries( + ${Qt_LIBS} +) + +set(LIB_NAME login-udcp) + +aux_source_directory(. SRCS) + +add_library(${LIB_NAME} SHARED ${SRCS} login-plugin.qrc) + +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/examples/login-plugins/login-udcp/images/next1.png b/plugins/examples/login-plugins/login-udcp/images/next1.png new file mode 100644 index 00000000..238182ac Binary files /dev/null and b/plugins/examples/login-plugins/login-udcp/images/next1.png differ diff --git a/plugins/examples/login-plugins/login-udcp/images/next2.png b/plugins/examples/login-plugins/login-udcp/images/next2.png new file mode 100644 index 00000000..41995d4a Binary files /dev/null and b/plugins/examples/login-plugins/login-udcp/images/next2.png differ diff --git a/plugins/examples/login-plugins/login-udcp/login-plugin.qrc b/plugins/examples/login-plugins/login-udcp/login-plugin.qrc new file mode 100644 index 00000000..0936c48e --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/login-plugin.qrc @@ -0,0 +1,7 @@ + + + images/next1.png + images/next2.png + qss/udcp_mfa_login_widget.qss + + \ No newline at end of file diff --git a/plugins/examples/login-plugins/login-udcp/login.json b/plugins/examples/login-plugins/login-udcp/login.json new file mode 100644 index 00000000..95156e4b --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/login.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Login" +} diff --git a/plugins/examples/login-plugins/login-udcp/qss/udcp_mfa_login_widget.qss b/plugins/examples/login-plugins/login-udcp/qss/udcp_mfa_login_widget.qss new file mode 100644 index 00000000..ef6f3af3 --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/qss/udcp_mfa_login_widget.qss @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +QPushButton#sendButton { + background-color: rgba(255, 255, 255, 76); + color: white; + border: none; + height: 32; + border-radius: 6px; + padding-left: 8px; + padding-right: 8px; +} + +QPushButton#sendButton:hover { + background-color: #0081ff; +} + +QPushButton#sendButton:pressed { + color: rgb(180, 180, 180); +} +QPushButton#sendButton:!enabled { + color: rgb(200, 200, 200); +} + +QPushButton#verifyButton { + background-color: transparent; + border-radius: 2px; + color: white; + width: 28; + height: 20; + border: none; +} + +QPushButton#verifyButton:hover { + background-color: #0081ff; +} diff --git a/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.cpp b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.cpp new file mode 100644 index 00000000..f91133a3 --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.cpp @@ -0,0 +1,168 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "udcp_mfa_login_module.h" + +#include + +static QString success_reply(const QJsonValue &data) +{ + QJsonObject reply { + {"Code", 0}, + {"Message", "Success"}, + {"Data", data} + }; + return QJsonDocument(reply).toJson(QJsonDocument::Compact); +} + +namespace dss { +namespace module_v2 { + +UdcpMFALoginModule::UdcpMFALoginModule(QObject *parent) + : QObject(parent) +{ + setObjectName("LoginModule"); +} + +UdcpMFALoginModule::~UdcpMFALoginModule() noexcept +{ + if (m_mainWindow) { + delete m_mainWindow; + m_mainWindow = nullptr; + } +} + +QString UdcpMFALoginModule::message(const QString &msg) +{ + qDebug() << Q_FUNC_INFO << "received a message:" << msg; + + auto doc = QJsonDocument::fromJson(msg.toUtf8()); + + if (!doc.isObject()) { + qWarning() << "given message is not an json object"; + return {}; + } + + auto obj = doc.object(); + auto cmd = obj.value("CmdType").toString(); + auto data = obj.value("Data").toObject(); + + if (cmd == "CurrentUserChanged") { + return success_reply({}); + + } else if (cmd == "GetConfigs") { + QJsonObject payload { + {"ShowAvatar", true}, + {"ShowUserName", true}, + {"ShowSwitchButton", false}, + {"ShowLockButton", false}, + {"DefaultAuthLevel", DefaultAuthLevel::StrongDefault}, + {"DisableOtherAuthentications", true}}; + return success_reply(payload); + + } else if (cmd == "AuthState") { + return success_reply({}); + + } else if (cmd == "GetLevel") { + QJsonObject payload { + {"Level", 2}}; + return success_reply(payload); + + } else if (cmd == "StartAuth") { + m_mainWindow->setFocus(); + return success_reply({}); + + } else if (cmd == "GetLoginType") { + QJsonObject payload { + {"LoginType", 1} + }; + return success_reply(payload); + + } else if (cmd == "GetSessionTimeout") { + QJsonObject payload { + {"SessionTimeout", 30 * 1000} + }; + return success_reply(payload); + + } else if (cmd == "UpdateLoginType") { + QJsonObject payload { + {"LoginType", 0} + }; + return success_reply(payload); + + + } else if (cmd == "HasSecondLevel") { + QJsonObject payload { + {"HasSecondLevel", true} + }; + return success_reply(payload); + } + + return success_reply({}); +} + +void UdcpMFALoginModule::reset() +{ + qDebug() << Q_FUNC_INFO << "login module reset"; + init(); +} + +void UdcpMFALoginModule::init() +{ + initData(); + if (m_mainWindow) { + m_mainWindow->reset(); + } else { + initUI(); + initConnections(); + } +} + +void UdcpMFALoginModule::initUI() +{ + m_mainWindow = new UdcpMFALoginWidget(m_user); +} + +void UdcpMFALoginModule::initConnections() +{ + connect(m_mainWindow, &UdcpMFALoginWidget::finished, [this] { + AuthCallbackData data; + data.result = AuthResult::Success; + data.account = m_user; + data.token = "1"; + m_authCallback(&data, m_appData); + }); +} + +void UdcpMFALoginModule::initData() +{ + if (!m_messageCallback) { + qWarning() << "message callback func is null"; + return; + } + + // 发送获取属性的请求 + QJsonArray dataArr {"AppType", "CurrentUser"}; + QJsonObject obj { + {"CmdType", "GetProperties"}, + {"Data", dataArr} + }; + + auto result = m_messageCallback(QJsonDocument(obj).toJson(QJsonDocument::Compact), m_appData); + qDebug() << "received property result:" << result; + + auto doc = QJsonDocument::fromJson(result.toUtf8()); + if (!doc.isObject()) { + return; + } + + auto reply = doc.object(); + auto data = reply["Data"].toObject(); + auto user = data["CurrentUser"].toObject(); + m_user = user["Name"].toString(); +} + +} +} + diff --git a/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.h b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.h new file mode 100644 index 00000000..78877d5a --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_module.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UDCP_LOGIN_MODULE_H +#define UDCP_LOGIN_MODULE_H + +#include "login_module_interface_v2.h" +#include "udcp_mfa_login_widget.h" + +namespace dss { +namespace module_v2 { + +class UdcpMFALoginModule: public QObject, + public dss::module_v2::LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) +public: + + explicit UdcpMFALoginModule(QObject *parent = nullptr); + ~UdcpMFALoginModule() noexcept override; + QString message(const QString &msg) override; + void reset() override; + void init() override; + inline void setAuthCallback(AuthCallbackFun func) override { m_authCallback = func; } + inline void setMessageCallback(MessageCallbackFunc func) override { m_messageCallback = func; } + inline void setAppData(AppDataPtr data) override { m_appData = data; } + inline QWidget *content() override { return m_mainWindow; } + inline QString key() const override { return objectName(); } + inline QString icon() const override { return "code-block"; } + inline ModuleType type() const override { return LoginType; } + +private: + void initUI(); + void initData(); + void initConnections(); + +private: + + AppDataPtr m_appData{}; + + AuthCallbackFun m_authCallback{}; + + MessageCallbackFunc m_messageCallback{}; + + UdcpMFALoginWidget *m_mainWindow{}; + + QString m_user {}; + + int m_appType{}; +}; + +} +} + +#endif // UDCP_LOGIN_MODULE_H diff --git a/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.cpp b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.cpp new file mode 100644 index 00000000..7cf79e23 --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.cpp @@ -0,0 +1,162 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "udcp_mfa_login_widget.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static void set_style(QWidget *widget, const QString &path) +{ + QFile file(path); + file.open(QFile::ReadOnly); + auto content = file.readAll(); + file.close(); + widget->setStyleSheet(content); +} + +UdcpMFALoginWidget::UdcpMFALoginWidget(const QString &user, QWidget *parent) + : QWidget(parent) + , m_timer(new QTimer(this)) + , m_phoneEdit(new QLineEdit("1592****994", this)) + , m_sendButton(new QPushButton(tr("发送验证码"), this)) + , m_codeEdit(new QLineEdit(this)) + , m_verifyButton(new QPushButton(QIcon(":/images/next1.png"), "", m_codeEdit)) +{ + set_style(this, ":/qss/udcp_mfa_login_widget.qss"); + initUI(); + initConnections(); +} +void UdcpMFALoginWidget::initUI() +{ + m_phoneEdit->setObjectName("phoneEdit"); + m_phoneEdit->setContextMenuPolicy(Qt::NoContextMenu); + if (m_phoneEdit->text().isEmpty()) { + m_phoneEdit->setPlaceholderText(tr("请输入手机号")); + QRegularExpression phoneRegExp("^1[3-9]\\d{9}$"); + m_phoneEdit->setValidator(new QRegularExpressionValidator(phoneRegExp, this)); + } else { + m_phoneEdit->setDisabled(true); + } + + m_sendButton->setObjectName("sendButton"); + m_sendButton->setEnabled(!m_phoneEdit->isEnabled()); + m_sendButton->setFixedWidth(100); + + auto *topLayout = new QHBoxLayout; + topLayout->addWidget(m_phoneEdit); + topLayout->addWidget(m_sendButton); + + m_codeEdit->setTextMargins(0, 0, 30, 0); + m_codeEdit->setMinimumWidth(280); + m_codeEdit->setPlaceholderText(tr("请输入验证码")); + m_codeEdit->setContextMenuPolicy(Qt::NoContextMenu); + m_codeEdit->setObjectName("codeEdit"); + QRegularExpression codeRegExp("^\\d{4}$"); + m_codeEdit->setValidator(new QRegularExpressionValidator(codeRegExp, this)); + + m_verifyButton->setObjectName("verifyButton"); + m_verifyButton->setCursor(Qt::ArrowCursor); + m_verifyButton->setContentsMargins(0, 0, 0, 0); + m_verifyButton->setEnabled(false); + + auto codeLayout = new QHBoxLayout(m_codeEdit); + codeLayout->setContentsMargins(8, 0, 8, 0); + codeLayout->addStretch(1); + codeLayout->addWidget(m_verifyButton, 0, Qt::AlignRight | Qt::AlignVCenter); + + auto *layout = new QVBoxLayout; + layout->addLayout(topLayout); + layout->addWidget(m_codeEdit); + + setLayout(layout); + + if (m_phoneEdit->isEnabled()) { + setFocusProxy(m_phoneEdit); + } else { + setFocusProxy(m_codeEdit); + } +} + +void UdcpMFALoginWidget::initConnections() +{ + if (m_phoneEdit->isEnabled()) { + connect(m_phoneEdit, &QLineEdit::textChanged, [this] { + if (m_phoneEdit->hasAcceptableInput() && m_timer->isActive()) { + return; + } + m_sendButton->setEnabled(m_phoneEdit->hasAcceptableInput()); + }); + } + + connect(m_timer, &QTimer::timeout, [this] { + if (--m_count <= 0) { + m_sendButton->setText(tr("获取验证码")); + m_sendButton->setEnabled(m_phoneEdit->hasAcceptableInput()); + m_timer->stop(); + } else { + m_sendButton->setText(QString("%1s").arg(m_count)); + } + }); + + connect(m_sendButton, &QPushButton::clicked, [this] { + // 按钮禁用,按钮显示倒计时60s,60s后按钮启用 + m_sendButton->setEnabled(false); + m_timer->setInterval(1000); + m_count = 60; + m_sendButton->setText(QString("%1s").arg(m_count)); + m_timer->start(); + }); + + connect(m_verifyButton, &QPushButton::pressed, [this] { + m_verifyButton->setIcon(QIcon(":/images/next2.png")); + }); + connect(m_verifyButton, &QPushButton::released, [this] { + m_verifyButton->setIcon(QIcon(":/images/next1.png")); + }); + connect(m_codeEdit, &QLineEdit::textChanged, [this] { + m_verifyButton->setEnabled(m_codeEdit->hasAcceptableInput()); + }); + connect(m_codeEdit, &QLineEdit::returnPressed, [this] { + if (m_phoneEdit->hasAcceptableInput()) { + m_verifyButton->click(); + } + }); + connect(m_verifyButton, &QPushButton::clicked, [this] { + Q_EMIT finished(); + }); +} + + +void UdcpMFALoginWidget::reset() +{ + m_count = 0; + m_timer->stop(); + m_phoneEdit->setText("1592****994"); + m_codeEdit->clear(); + m_phoneEdit->disconnect(); + m_phoneEdit->setEnabled(m_phoneEdit->text().isEmpty()); + m_sendButton->setText(tr("获取验证码")); + m_sendButton->setEnabled(!m_phoneEdit->isEnabled()); + if (m_phoneEdit->isEnabled()) { + m_phoneEdit->setPlaceholderText(tr("请输入手机号")); + QRegularExpression phoneRegExp("^1[3-9]\\d{9}$"); + m_phoneEdit->setValidator(new QRegularExpressionValidator(phoneRegExp, this)); + connect(m_phoneEdit, &QLineEdit::textChanged, [this] { + if (m_phoneEdit->hasAcceptableInput() && m_timer->isActive()) { + return; + } + m_sendButton->setEnabled(m_phoneEdit->hasAcceptableInput()); + }); + setFocusProxy(m_phoneEdit); + } else { + setFocusProxy(m_codeEdit); + } +} diff --git a/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.h b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.h new file mode 100644 index 00000000..9b679b14 --- /dev/null +++ b/plugins/examples/login-plugins/login-udcp/udcp_mfa_login_widget.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + + +#ifndef UDCP_MFA_LOGIN_WIDGET_H +#define UDCP_MFA_LOGIN_WIDGET_H + +#include + +class QLineEdit; +class QPushButton; +class UdcpMFALoginWidget: public QWidget +{ + Q_OBJECT +public: + explicit UdcpMFALoginWidget(const QString &user, QWidget *parent = Q_NULLPTR); + void reset(); + +Q_SIGNALS: + void finished(); + +private: + void initUI(); + void initConnections(); + + int m_count {}; // 倒计时 + const QString m_user {}; + + QTimer *m_timer {}; + QLineEdit *m_phoneEdit {}; + QPushButton *m_sendButton {}; + QLineEdit *m_codeEdit {}; + QPushButton *m_verifyButton {}; +}; + +#endif // UDCP_MFA_LOGIN_WIDGET_H diff --git a/modules/examples/network/CMakeLists.txt b/plugins/examples/tray-plugins/network/CMakeLists.txt similarity index 75% rename from modules/examples/network/CMakeLists.txt rename to plugins/examples/tray-plugins/network/CMakeLists.txt index b8c191e1..b2cf5755 100644 --- a/modules/examples/network/CMakeLists.txt +++ b/plugins/examples/tray-plugins/network/CMakeLists.txt @@ -1,5 +1,4 @@ include_directories( - ${DFrameworkDBus_INCLUDE_DIRS} global ) @@ -11,8 +10,6 @@ set(LIB_NAME network) aux_source_directory(. SRCS) -# add_library(${LIB_NAME} STATIC ${SRCS}) - add_library(${LIB_NAME} SHARED ${SRCS}) install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/examples/tray-plugins/network/network.json b/plugins/examples/tray-plugins/network/network.json new file mode 100644 index 00000000..0b3bf7f6 --- /dev/null +++ b/plugins/examples/tray-plugins/network/network.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Tray" +} diff --git a/modules/examples/network/network_module.cpp b/plugins/examples/tray-plugins/network/network_module.cpp similarity index 72% rename from modules/examples/network/network_module.cpp rename to plugins/examples/tray-plugins/network/network_module.cpp index 15d68153..d93993a7 100644 --- a/modules/examples/network/network_module.cpp +++ b/plugins/examples/tray-plugins/network/network_module.cpp @@ -1,29 +1,15 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "network_module.h" #include #include #include +#include +#include +#include namespace dss { namespace module { diff --git a/modules/examples/network/network_module.h b/plugins/examples/tray-plugins/network/network_module.h similarity index 58% rename from modules/examples/network/network_module.h rename to plugins/examples/tray-plugins/network/network_module.h index 34f59225..d5116057 100644 --- a/modules/examples/network/network_module.h +++ b/plugins/examples/tray-plugins/network/network_module.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGIN_MODULE_H #define LOGIN_MODULE_H diff --git a/modules/examples/webview/CMakeLists.txt b/plugins/examples/tray-plugins/webview/CMakeLists.txt similarity index 100% rename from modules/examples/webview/CMakeLists.txt rename to plugins/examples/tray-plugins/webview/CMakeLists.txt diff --git a/plugins/examples/tray-plugins/webview/webview.json b/plugins/examples/tray-plugins/webview/webview.json new file mode 100644 index 00000000..0b3bf7f6 --- /dev/null +++ b/plugins/examples/tray-plugins/webview/webview.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Tray" +} diff --git a/plugins/examples/tray-plugins/webview/webview_content.cpp b/plugins/examples/tray-plugins/webview/webview_content.cpp new file mode 100644 index 00000000..a19441c8 --- /dev/null +++ b/plugins/examples/tray-plugins/webview/webview_content.cpp @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "webview_content.h" + +#include + +namespace dss { +namespace module { + +WebviewContent::WebviewContent(QWidget *parent) + : QWidget(parent) + , m_mainLayout(nullptr) + , m_webview(nullptr) +{ + setObjectName(QStringLiteral("WebviewContent")); + setAccessibleName(QStringLiteral("WebviewContent")); + + setFixedSize(600, 500); + + initUI(); +} + +void WebviewContent::initUI() +{ + m_mainLayout = new QVBoxLayout(this); + + m_webview = new QWebEngineView(this); + m_webview->load(QUrl("http://detectportal.deepin.com")); + + m_mainLayout->addWidget(m_webview); +} + +} // namespace module +} // namespace dss diff --git a/plugins/examples/tray-plugins/webview/webview_content.h b/plugins/examples/tray-plugins/webview/webview_content.h new file mode 100644 index 00000000..38d2f0fd --- /dev/null +++ b/plugins/examples/tray-plugins/webview/webview_content.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WEBVIEWCONTENT_H +#define WEBVIEWCONTENT_H + +#include +#include + +class QVBoxLayout; + +namespace dss { +namespace module { + +class WebviewContent : public QWidget +{ + Q_OBJECT + +public: + explicit WebviewContent(QWidget *parent = nullptr); + +private: + void initUI(); + +private: + QVBoxLayout *m_mainLayout; + QWebEngineView *m_webview; +}; + +} // namespace module +} // namespace dss +#endif // WEBVIEWCONTENT_H diff --git a/plugins/examples/tray-plugins/webview/webview_module.cpp b/plugins/examples/tray-plugins/webview/webview_module.cpp new file mode 100644 index 00000000..32b236e5 --- /dev/null +++ b/plugins/examples/tray-plugins/webview/webview_module.cpp @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "webview_module.h" + +#include + +namespace dss { +namespace module { + +WebviewModule::WebviewModule(QObject *parent) + : QObject(parent) + , m_webviewContent(nullptr) +{ + setObjectName(QStringLiteral("WebviewModule")); +} + +WebviewModule::~WebviewModule() +{ + if (m_webviewContent) { + delete m_webviewContent; + } +} + +void WebviewModule::init() +{ + initUI(); +} + +void WebviewModule::initUI() +{ + if (m_webviewContent) { + return; + } + m_webviewContent = new WebviewContent(); +} + +} // namespace module +} // namespace dss diff --git a/modules/examples/webview/webview_module.h b/plugins/examples/tray-plugins/webview/webview_module.h similarity index 51% rename from modules/examples/webview/webview_module.h rename to plugins/examples/tray-plugins/webview/webview_module.h index 97ad185b..582ea781 100644 --- a/modules/examples/webview/webview_module.h +++ b/plugins/examples/tray-plugins/webview/webview_module.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGIN_MODULE_H #define LOGIN_MODULE_H @@ -44,6 +27,10 @@ class WebviewModule : public QObject inline QString key() const override { return objectName(); } QWidget *content() override { return m_webviewContent; } inline QString icon() const override { return ":/img/deepin-system-monitor.svg"; } + QWidget *itemWidget() const override { return nullptr; } + QWidget *itemTipsWidget() const override { return nullptr; } + const QString itemContextMenu() const override { return QString(); } + void invokedMenuItem(const QString &menuId, const bool checked) const override { } private: void initUI(); diff --git a/plugins/login-gesture/CMakeLists.txt b/plugins/login-gesture/CMakeLists.txt new file mode 100644 index 00000000..2ce96ce6 --- /dev/null +++ b/plugins/login-gesture/CMakeLists.txt @@ -0,0 +1,72 @@ +find_package(DtkWidget REQUIRED) +find_package(DtkCore REQUIRED) + +include(GNUInstallDirs) + +include_directories( + ${DFrameworkDBus_INCLUDE_DIRS} + global + src + resetDialog + utils +) + +link_libraries( + ${Qt_LIBS} + ${DtkWidget_LIBRARIES} + ${DtkCore_LIBRARIES} + crypt +) + +set(LIB_NAME login-gesture) +set(BIN_NAME reset-pattern-dialog) + +file(GLOB_RECURSE SHARED_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.cpp +) + +file(GLOB_RECURSE LIB_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/loginPlugin/*.cpp +) + +file(GLOB_RECURSE RESET_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/resetDialog/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/resetDialog/*.qrc +) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + ADD_DEFINITIONS(-DQM_FILES_DIR="${CMAKE_BINARY_DIR}/plugins/login-gesture/translations") +else() + ADD_DEFINITIONS(-DQM_FILES_DIR="/usr/share/dde-gesture-login/translations") +endif() + +set(QRCS + ${CMAKE_CURRENT_SOURCE_DIR}/gesture.qrc +) + +add_library(${LIB_NAME} SHARED + ${SHARED_SOURCE} + ${LIB_SOURCE} + ${QRCS} +) +set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) + +add_executable(${BIN_NAME} + ${SHARED_SOURCE} + ${RESET_SOURCE} + ${QRCS} +) + +execute_process(COMMAND bash "${CMAKE_CURRENT_SOURCE_DIR}/translate_generation.sh" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) +install(TARGETS ${BIN_NAME} DESTINATION lib/dde-control-center) + +file(GLOB QM_FILES "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.qm") +install(FILES ${QM_FILES} DESTINATION share/dde-gesture-login/translations) + +install(FILES configs/login-gesture.json DESTINATION /lib/dde-session-shell/modules/config.d) +install(FILES configs/org.deepin.dde.dss-login-gesture.json DESTINATION ${CMAKE_INSTALL_DATADIR}/dsg/configs/org.deepin.dde.lock) +install(FILES configs/org.deepin.dde.dss-login-gesture.json DESTINATION ${CMAKE_INSTALL_DATADIR}/dsg/configs/org.deepin.dde.lightdm-deepin-greeter) \ No newline at end of file diff --git a/plugins/login-gesture/configs/login-gesture.json b/plugins/login-gesture/configs/login-gesture.json new file mode 100644 index 00000000..241eb1b8 --- /dev/null +++ b/plugins/login-gesture/configs/login-gesture.json @@ -0,0 +1,20 @@ +{ + "pluginEnabled": { + "lock": { + "dconfig": { + "appid": "org.deepin.dde.lock", + "resource": "org.deepin.dde.dss-login-gesture", + "subpath": "", + "key": "pluginEnabled" + } + }, + "greeter": { + "dconfig": { + "appid": "org.deepin.dde.lightdm-deepin-greeter", + "resource": "org.deepin.dde.dss-login-gesture", + "subpath": "", + "key": "pluginEnabled" + } + } + } +} \ No newline at end of file diff --git a/plugins/login-gesture/configs/org.deepin.dde.dss-login-gesture.json b/plugins/login-gesture/configs/org.deepin.dde.dss-login-gesture.json new file mode 100644 index 00000000..c209d0a9 --- /dev/null +++ b/plugins/login-gesture/configs/org.deepin.dde.dss-login-gesture.json @@ -0,0 +1,16 @@ +{ + "magic": "dsg.config.meta", + "version": "1.0", + "contents": { + "pluginEnabled": { + "value": false, + "serial": 0, + "flags": ["global"], + "name": "PluginEnabled", + "name[zh_CN]": "是否启用插件", + "description[zh_CN]": "是否启用插件,默认为否。", + "permissions": "readwrite", + "visibility": "private" + } + } +} diff --git a/plugins/login-gesture/gesture.qrc b/plugins/login-gesture/gesture.qrc new file mode 100644 index 00000000..29890590 --- /dev/null +++ b/plugins/login-gesture/gesture.qrc @@ -0,0 +1,5 @@ + + + icons/firstEnroll.svg + + diff --git a/plugins/login-gesture/icons/firstEnroll.svg b/plugins/login-gesture/icons/firstEnroll.svg new file mode 100644 index 00000000..ca0cf976 --- /dev/null +++ b/plugins/login-gesture/icons/firstEnroll.svg @@ -0,0 +1,35 @@ + + + icon/手势密码@2x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/login-gesture/login.json b/plugins/login-gesture/login.json new file mode 100644 index 00000000..bec81f0d --- /dev/null +++ b/plugins/login-gesture/login.json @@ -0,0 +1,3 @@ +{ + "api": "2.0.0" +} diff --git a/plugins/login-gesture/loginPlugin/gestureloginmodule.cpp b/plugins/login-gesture/loginPlugin/gestureloginmodule.cpp new file mode 100644 index 00000000..7f21c5f3 --- /dev/null +++ b/plugins/login-gesture/loginPlugin/gestureloginmodule.cpp @@ -0,0 +1,230 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gestureloginmodule.h" +#include "waypointmodel.h" +#include "modulewidget.h" +#include "userservice.h" +#include "gestureauthworker.h" +#include "gesturemodifyworker.h" + +using namespace gestureLogin; +using namespace gestureSetting; + +namespace dss { +namespace module_v2 { + +GestureLoginModule::GestureLoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_messageCallback(nullptr) + , m_loginWidget(nullptr) + , m_appType(AppType::Lock) +{ + setObjectName(QStringLiteral("gesture-login-plugin")); + // CAUTION: do not call initui here + // when object created, it's not in GUI thread +} + +GestureLoginModule::~GestureLoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget.data(); + } +} + +void GestureLoginModule::init() +{ + updateInfo(); + initWorker(); +} + +QWidget *GestureLoginModule::content() +{ + return m_loginWidget; +} + +void GestureLoginModule::reset() +{ + initUI(); + init(); +} + +void GestureLoginModule::sendToken(const QString &token) +{ + AuthCallbackData data; + data.account = ""; + data.token = token; + data.result = 1; // 固定值,代表本地验证通过,通知dss去校验密码 + m_authCallback(&data, m_appData); +} + +void GestureLoginModule::enroll(const QString &token) +{ + UserService::instance()->enroll(token); +} + +void GestureLoginModule::initUI() +{ + if (m_loginWidget) { + qobject_cast(m_loginWidget)->reset(); + return; + } + + m_loginWidget = new ModuleWidget(); +} + +void GestureLoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void GestureLoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void GestureLoginModule::setMessageCallback(MessageCallbackFunc messageCallback) +{ + m_messageCallback = messageCallback; +} + +void GestureLoginModule::updateInfo() +{ + if (!m_messageCallback) { + qWarning() << "message callback func is nullptr"; + return; + } + + // 发送获取属性的请求 + QJsonObject message; + message.insert("CmdType", "GetProperties"); + QJsonArray array; + array.append("AppType"); + array.append("CurrentUser"); + message["Data"] = array; + QJsonDocument doc; + doc.setObject(message); + QString ret = m_messageCallback(doc.toJson(), m_appData); + + // 解析返回值 + QJsonParseError jsonParseError; + const QJsonDocument retDoc = QJsonDocument::fromJson(ret.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || retDoc.isEmpty()) { + qWarning() << "Failed to analysis AppType info from shell!: " << ret; + return; + } + + QJsonObject obj = retDoc.object(); + if (obj.value("Code").toInt() != 0) { + qWarning() << "Get properties failed, message: " << obj.value("Message").toString(); + return; + } + + QJsonObject data = obj.value("Data").toObject(); + if (data.contains("AppType")) { + m_appType = data.value("AppType").toInt(); + qInfo() << "App type: " << m_appType; + } + + if (data.contains("CurrentUser")) { + QJsonObject user = data.value("CurrentUser").toObject(); + updateUser(user.value("Name").toString()); + qInfo() << "Current user: " << user; + } +} + +void GestureLoginModule::initWorker() +{ + UserService::instance()->setUserName(m_userName); + + auto model = WayPointModel::instance(); + auto gestureState = model->getGestureState(); + + // 无手势,直接开始录入 + if (gestureState == GestureState::NotSet || gestureState == GestureState::SetAndRemoved) { + model->setCurrentMode(Mode::Enroll); + } else { + model->setCurrentMode(Mode::Auth); + } + + // 创建认证流程控制 + auto connectType = Qt::AutoConnection | Qt::UniqueConnection; + // 注意只创建一个对象 + static GestureAuthWorker *authWorker = new GestureAuthWorker(this); + authWorker->setActive(model->currentMode() == Mode::Auth); + connect(this, &GestureLoginModule::onAuthStateChanged, authWorker, &GestureAuthWorker::onAuthStateChanged, Qt::ConnectionType(connectType)); + connect(this, &GestureLoginModule::onLimitsInfoChanged, authWorker, &GestureAuthWorker::onLimitsInfoChanged, Qt::ConnectionType(connectType)); + connect(authWorker, &GestureAuthWorker::requestSendToken, this, &GestureLoginModule::sendToken, Qt::ConnectionType(connectType)); + + // 创建录入流程控制 + static GestureModifyWorker *enrollWorker = new GestureModifyWorker(this); + enrollWorker->setActive(model->currentMode() == Mode::Enroll); + connect(enrollWorker, &GestureModifyWorker::requestSaveToken, this, &GestureLoginModule::enroll, Qt::ConnectionType(connectType)); +} + +// 是否可以由dss去控制这个配置变化 +void GestureLoginModule::updateUser(const QString &userName) +{ + if (m_userName == userName) { + return; + } + + m_userName = userName; + initWorker(); +} + +QString GestureLoginModule::message(const QString &message) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + qWarning() << "Failed to obtain message from shell!: " << message; + return ""; + } + + QJsonObject retObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + + QJsonObject msgObj = messageDoc.object(); + QString cmdType = msgObj.value("CmdType").toString(); + QJsonObject data = msgObj.value("Data").toObject(); + qInfo() << "Cmd type: " << cmdType; + if (cmdType == "CurrentUserChanged") { + updateUser(data.value("Name").toString()); + qDebug() << "Current user changed, user name: " << m_userName; + } else if (cmdType == "GetConfigs") { + QJsonObject retDataObj; + retDataObj["ShowAvatar"] = false; + retDataObj["ShowUserName"] = false; + retDataObj["ShowSwitchButton"] = false; + retDataObj["ShowLockButton"] = false; + retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::Default; + retDataObj["DisableOtherAuthentications"] = false; + retDataObj["AuthType"] = AuthType::AT_Pattern; + retObj["Data"] = retDataObj; + } else if (cmdType == "AuthState") { + int authType = data.value("AuthType").toInt(); + int authState = data.value("AuthState").toInt(); + // 处理认证结果 + // 注意录入相关不在此处理 + Q_EMIT onAuthStateChanged(authType, authState); + } else if (cmdType == "LimitsInfo") { + bool locked = data.value("Locked").toBool(); + int maxTries = data.value("MaxTries").toInt(); + int numFailures = data.value("NumFailures").toInt(); + int unlockSecs = data.value("UnlockSecs").toInt(); + QString unlockTime = data.value("UnlockTime").toString(); + Q_EMIT onLimitsInfoChanged(locked, maxTries, numFailures, unlockSecs, unlockTime); + } + + QJsonDocument doc; + doc.setObject(retObj); + return doc.toJson(); +} + +} // namespace module_v2 +} // namespace dss diff --git a/plugins/login-gesture/loginPlugin/gestureloginmodule.h b/plugins/login-gesture/loginPlugin/gestureloginmodule.h new file mode 100644 index 00000000..f06814f7 --- /dev/null +++ b/plugins/login-gesture/loginPlugin/gestureloginmodule.h @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef GESTURELOGINMODULE_H +#define GESTURELOGINMODULE_H + +#include "login_module_interface_v2.h" + +#include +#include + +class GesturePannel; + +namespace dss { +namespace module_v2 { + +class GestureLoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + +public: + enum DefaultAuthLevel { + NoDefault = 0, + Default, + StrongDefault + }; + + explicit GestureLoginModule(QObject *parent = nullptr); + ~GestureLoginModule() override; + + void init() override; + inline QString key() const override { return objectName(); } + QWidget *content() override; + inline QString icon() const override { return "code-gesture"; } + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + void setMessageCallback(MessageCallbackFunc) override; + QString message(const QString &) override; + void reset() override; + +public Q_SLOTS: + void sendToken(const QString &); + void enroll(const QString &); + +Q_SIGNALS: + void onAuthStateChanged(int, int); + void onLimitsInfoChanged(bool, int, int, int, const QString &); + +private: + void initUI(); + void updateInfo(); + void initWorker(); + void updateUser(const QString &); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + MessageCallbackFunc m_messageCallback; + QPointer m_loginWidget; + QString m_userName; + int m_appType; +}; + +} // namespace module_v2 +} // namespace dss +#endif // GESTURELOGINMODULE_H diff --git a/plugins/login-gesture/lupdate.sh b/plugins/login-gesture/lupdate.sh new file mode 100755 index 00000000..1f477afb --- /dev/null +++ b/plugins/login-gesture/lupdate.sh @@ -0,0 +1,5 @@ +#!/bin/bash +lupdate ./ -ts -no-obsolete -locations none translations/login-gesture_en.ts +lupdate ./ -ts -no-obsolete -locations none translations/login-gesture_zh_CN.ts +lupdate ./ -ts -no-obsolete -locations none translations/login-gesture_zh_TW.ts +lupdate ./ -ts -no-obsolete -locations none translations/login-gesture_zh_HK.ts diff --git a/plugins/login-gesture/resetDialog/gesturedialog.cpp b/plugins/login-gesture/resetDialog/gesturedialog.cpp new file mode 100644 index 00000000..af525835 --- /dev/null +++ b/plugins/login-gesture/resetDialog/gesturedialog.cpp @@ -0,0 +1,260 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gesturedialog.h" +#include "gesturepannel.h" +#include "modulewidget.h" +#include "resetpatterncontroller.h" +#include "waypointmodel.h" +#include "translastiondoc.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace gestureSetting; +using namespace gestureLogin; + +GestureDialog::GestureDialog(ResetPatternController *worker, QWidget *parent) + : QWidget(parent) + , m_handle(new DPlatformWindowHandle(this)) + , m_titleBar(new QWidget(this)) + , m_mainContent(new QWidget(this)) + , m_mainLayout(new QStackedLayout(m_mainContent)) + , m_authWidget(new ModuleWidget(m_mainContent)) + , m_successWidget(new QWidget(m_mainContent)) + , m_confirmButton(nullptr) + , m_worker(worker) +{ + initUi(); + initConnection(); +} + +GestureDialog::~GestureDialog() {} + +void GestureDialog::initUi() +{ + setAccessibleName("ResetGesturePage"); + + m_handle->setEnableSystemMove(false); + m_handle->setShadowOffset(QPoint(5, 5)); + m_handle->setShadowRadius(20); + + m_titleBar->setFixedHeight(50 * qApp->devicePixelRatio()); + QHBoxLayout *layoutTitle = new QHBoxLayout(m_titleBar); + layoutTitle->setContentsMargins(10, 0, 10, 0); + layoutTitle->setSpacing(0); + // 警告图标 + layoutTitle->addWidget(createTitleIcon(QIcon::fromTheme("dialog-warning"))); + layoutTitle->addStretch(); + // 右侧关闭按钮 + QLabel *closeButton = createTitleIcon(QIcon::fromTheme("dialog-close")); + closeButton->setCursor(Qt::PointingHandCursor); + closeButton->setObjectName("close_button"); + closeButton->installEventFilter(this); + layoutTitle->addWidget(closeButton); + + auto *mainContentLayout = new QVBoxLayout(this); + mainContentLayout->setContentsMargins(0, 0, 0, 0); + mainContentLayout->addWidget(m_titleBar, 0, Qt::AlignTop); + mainContentLayout->addSpacing(30); + mainContentLayout->addWidget(m_mainContent); + mainContentLayout->addWidget(createCancelButton(), 0, Qt::AlignBottom); + + m_mainContent->setMinimumHeight(605); + m_mainLayout->addWidget(m_authWidget); + createSuccessWidget(); + m_mainLayout->addWidget(m_successWidget); + m_mainLayout->setCurrentWidget(m_authWidget); +} + +void GestureDialog::initConnection() +{ + // token输入完成并且已经调用父进程写入 + connect(m_worker, &ResetPatternController::inputFinished, this, &GestureDialog::onInputFinished); + connect(m_confirmButton, &QPushButton::clicked, this, &GestureDialog::close); + m_titleBar->installEventFilter(this); +} + +QWidget* GestureDialog::createCancelButton() +{ + auto *cancelWidget = new QWidget(this); + QHBoxLayout *layout = new QHBoxLayout(cancelWidget); + layout->setContentsMargins(10, 0, 10, 10); + m_confirmButton = new QPushButton(TranslastionDoc::instance()->getDoc(DocIndex::Cancel), cancelWidget); + m_confirmButton->setAttribute(Qt::WA_NoMousePropagation); + layout->addWidget(m_confirmButton); + + return cancelWidget; +} + +QLabel *GestureDialog::createTitleIcon(const QIcon &icon) +{ + QLabel *label = new QLabel(m_titleBar); + QPixmap pixmap = icon.pixmap(QSize(40, 40) * qApp->devicePixelRatio()); + pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); + label->setFixedHeight(40 * qApp->devicePixelRatio()); + label->setPixmap(pixmap); + return label; +} + +void GestureDialog::createSuccessWidget() +{ + TranslastionDoc *transDoc = TranslastionDoc::instance(); + auto *resultLayout = new QVBoxLayout(m_successWidget); + resultLayout->setContentsMargins(0, 8, 0, 0); + + QLabel *labelTitle = new QLabel(m_successWidget); + DFontSizeManager::instance()->bind(labelTitle, DFontSizeManager::T3); + labelTitle->setAlignment(Qt::AlignCenter); + labelTitle->setText(transDoc->getDoc(DocIndex::SetPasswd)); + resultLayout->addWidget(labelTitle); + + auto *indicatorWidget = new QWidget(m_successWidget); + indicatorWidget->setFixedHeight(128); + indicatorWidget->setObjectName("indicatorSuccess"); + indicatorWidget->installEventFilter(this); + + resultLayout->addSpacing(10); + resultLayout->addWidget(indicatorWidget); + + auto *labelSuccess = new QLabel(transDoc->getDoc(DocIndex::EnrollDone), m_successWidget); + DFontSizeManager::instance()->bind(labelSuccess, DFontSizeManager::T5); + labelSuccess->setAlignment(Qt::AlignHCenter); + resultLayout->setSpacing(35); + resultLayout->addWidget(labelSuccess); + resultLayout->addStretch(); +} + +bool GestureDialog::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == m_titleBar) { + switch (event->type()) { + case QEvent::MouseButtonPress: { + QMouseEvent *mouseEvent = static_cast(event); + if ((mouseEvent->buttons().testFlag(Qt::LeftButton))) { + m_dragPosition = mapFromGlobal(mouseEvent->globalPos()); + } + } break; + case QEvent::MouseButtonRelease: { + m_dragPosition = QPoint(); + } break; + case QEvent::MouseMove: { + // 如果按下的点为空,则不做任何处理 + if (m_dragPosition.isNull()) + break; + + QMouseEvent *mouseEvent = static_cast(event); + int x = mouseEvent->globalX() - m_dragPosition.x(); + int y = mouseEvent->globalY() - m_dragPosition.y(); + + move(x, y); + } break; + default: break; + } + } else if (watched->isWidgetType()) { + QWidget *widget = qobject_cast(watched); + if (widget) { + if (widget->objectName() == "indicatorSuccess" && event->type() == QEvent::Paint) { + // 绘制图标 + QSvgRenderer renderer(QString(":/success.svg")); + QPixmap pixmap(QSize(128, 128) * qApp->devicePixelRatio()); + pixmap.fill(Qt::transparent); + QPainter painter; + painter.begin(&pixmap); + painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + painter.setPen(Qt::NoPen); + renderer.render(&painter); + painter.end(); + QSize pixmapSize(widget->height(), widget->height()); + QRect pixmapRect((widget->width() - pixmapSize.width()) / 2, + (widget->height() - pixmapSize.height()) / 2, + widget->height(), widget->height()); + painter.begin(widget); + painter.drawPixmap(pixmapRect, pixmap); + painter.end(); + } else if (widget->objectName() == "close_button" + && event->type() == QEvent::MouseButtonRelease) { + close(); + } + } + } + + return QWidget::eventFilter(watched, event); +} + +void GestureDialog::onInputFinished() +{ + // 两次校验通过 + m_mainLayout->setCurrentWidget(m_successWidget); + m_confirmButton->setText(TranslastionDoc::instance()->getDoc(DocIndex::Ok)); +} + +ResetPatternController *Manager::m_controller = nullptr; + +Manager::Manager(int old_file_id, int new_file_id, QObject *parent) + : QObject (parent) + , m_gestureDialog(nullptr) + , m_old_file_id (old_file_id) + , m_new_file_id(new_file_id) +{ +} + +Manager::~Manager() +{ + free(); + m_gestureDialog->deleteLater(); +} + +void Manager::start() +{ + if (m_gestureDialog) + return; + + if (!m_controller) { + m_controller = new ResetPatternController; + if (m_old_file_id >= 0) + m_controller->setOldPasswordFileId(m_old_file_id); + + if (m_new_file_id >= 0) + m_controller->setNewPasswordFileId(m_new_file_id); + + m_controller->start(); + } + + m_gestureDialog = new GestureDialog(m_controller); + + QDesktopWidget *desktopWidget = QApplication::desktop(); + m_gestureDialog->setFixedSize(380, 566); + int x = (desktopWidget->size().width() - m_gestureDialog->width()) / 2; + int y = (desktopWidget->size().height() - m_gestureDialog->height()) / 2; + m_gestureDialog->move(x, y); + m_gestureDialog->setWindowFlags(m_gestureDialog->windowFlags() | Qt::FramelessWindowHint); + m_gestureDialog->show(); +} + +void Manager::exit(int retCode) +{ + free(); + qDebug() << "exit code" << retCode; + qApp->quit(); +} + +void Manager::free() +{ + qDebug() << "free manager"; + if (m_controller) { + m_controller->close(); + m_controller->deleteLater(); + } +} diff --git a/plugins/login-gesture/resetDialog/gesturedialog.h b/plugins/login-gesture/resetDialog/gesturedialog.h new file mode 100644 index 00000000..9dcbcbc3 --- /dev/null +++ b/plugins/login-gesture/resetDialog/gesturedialog.h @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef GESTUREDIALOG_H +#define GESTUREDIALOG_H + +#include + +DWIDGET_USE_NAMESPACE + +class QStackedLayout; +class ResetPatternController; + +namespace gestureLogin { +class GesturePannel; +class ModuleWidget; +} + +DWIDGET_BEGIN_NAMESPACE +class DTitlebar; +class DPlatformWindowHandle; +DWIDGET_END_NAMESPACE + +namespace gestureSetting { + +class GestureDialog : public QWidget +{ + Q_OBJECT + +public: + explicit GestureDialog(ResetPatternController *worker, QWidget *parent = nullptr); + ~GestureDialog() override; + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; // 过滤鼠标事件 + +private: + void initUi(); + void initConnection(); + void createSuccessWidget(); + QWidget* createCancelButton(); + QLabel *createTitleIcon(const QIcon &icon); + +private slots: + void onInputFinished(); + +private: + DPlatformWindowHandle *m_handle; + QWidget *m_titleBar; + QWidget *m_mainContent; + QStackedLayout *m_mainLayout; + gestureLogin::ModuleWidget *m_authWidget; + QWidget *m_successWidget; + QPushButton *m_confirmButton; + ResetPatternController *m_worker; + QPoint m_dragPosition; +}; + +class Manager : public QObject +{ + Q_OBJECT + +public: + explicit Manager(int old_file_id, int new_file_id, QObject *parent = nullptr); + ~Manager() override; + + void start(); + + static void exit(int retCode); + static void free(); + +private: + static ResetPatternController *m_controller; + GestureDialog *m_gestureDialog; + int m_old_file_id; + int m_new_file_id; +}; + +} // namespace gestureSetting + +#endif // GESTUREDIALOG_H diff --git a/plugins/login-gesture/resetDialog/main.cpp b/plugins/login-gesture/resetDialog/main.cpp new file mode 100644 index 00000000..ea524ae8 --- /dev/null +++ b/plugins/login-gesture/resetDialog/main.cpp @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gesturedialog.h" + +#include +#include + +#include +#include +#include + +#include + +DCORE_USE_NAMESPACE +DWIDGET_USE_NAMESPACE + +using namespace gestureLogin; +using namespace gestureSetting; + +const bool IsWayland = qgetenv("XDG_SESSION_TYPE").contains("wayland"); + +double getScaleFormConfig() +{ + double defaultScaleFactor = 1.0; + QDBusInterface configInter("com.deepin.system.Display", + "/com/deepin/system/Display", + "com.deepin.system.Display", + QDBusConnection::systemBus()); + if (!configInter.isValid()) { + return defaultScaleFactor; + } + QDBusReply configReply = configInter.call("GetConfig"); + if (configReply.isValid()) { + QString config = configReply.value(); + QJsonParseError jsonError; + QJsonDocument jsonDoc(QJsonDocument::fromJson(config.toLatin1(), &jsonError)); + if (jsonError.error == QJsonParseError::NoError) { + QJsonObject rootObj = jsonDoc.object(); + QJsonObject Config = rootObj.value("Config").toObject(); + double scaleFactor = Config.value("ScaleFactors").toObject().value("ALL").toDouble(); + qDebug() << "Scale factor from system display config: " << scaleFactor; + if(scaleFactor == 0.0) { + scaleFactor = defaultScaleFactor; + } + return scaleFactor; + } + return defaultScaleFactor; + } + + qWarning() << "DBus call `GetConfig` failed, reply is invaild, error: " << configReply.error().message(); + return defaultScaleFactor; +} + +void setQtScaleFactorEnv() +{ + const double scaleFactor = getScaleFormConfig(); + qDebug() << "Final scale factor: " << scaleFactor; + if (scaleFactor > 0.0) { + qputenv("QT_SCALE_FACTOR", QByteArray::number(scaleFactor).toStdString().c_str()); + } else { + qputenv("QT_SCALE_FACTOR", "1"); + } +} + +int main(int argc, char *argv[]) +{ + if (qEnvironmentVariableIsEmpty("XDG_CURRENT_DESKTOP")) { + qputenv("XDG_CURRENT_DESKTOP", "Deepin"); + } + + if (IsWayland) { + setQtScaleFactorEnv(); + } + + QString user(qgetenv("USER")); + if (!user.isEmpty()) { + QString runtimeDirStr = QString("/tmp/runtime-%1").arg(user); + QFileInfo runtimeDir(runtimeDirStr); + if (runtimeDir.exists()) { + if (runtimeDir.isDir() && runtimeDir.owner() == user) { + qputenv("XDG_RUNTIME_DIR", runtimeDirStr.toUtf8()); + qputenv("DBUS_SESSION_BUS_ADDRESS", QString("%1/bus").arg(runtimeDirStr).toUtf8()); + } + } else { + qputenv("XDG_RUNTIME_DIR", runtimeDirStr.toUtf8()); + qputenv("DBUS_SESSION_BUS_ADDRESS", QString("%1/bus").arg(runtimeDirStr).toUtf8()); + } + } + + DApplication a(argc, argv); + a.setQuitOnLastWindowClosed(true); + a.setAttribute(Qt::AA_EnableHighDpiScaling, true); + a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); + + a.setOrganizationName("deepin"); + a.setApplicationName("reset-pattern-dialog"); + + // 由于这个应用是由deepin-password-admin管理,因此需要指定日志目录 + QString logPath = QString("/tmp/%1/%1.log").arg(a.applicationName()); + QDir logDir = QFileInfo(logPath).dir(); + if (!logDir.exists()) + logDir.mkdir(logDir.path()); + DLogManager::setlogFilePath(logPath); + DLogManager::registerFileAppender(); + DLogManager::registerConsoleAppender(); + + QCommandLineOption oldPwdOption(QStringList() << "old", "read current password which set it", "oldPasswordId"); + QCommandLineOption newPwdOption(QStringList() << "new", "write the new password which you will set", "newPasswordId"); + QCommandLineOption userOption(QStringList() << "u", "caller's name", "user"); + QCommandLineOption fOption(QStringList() << "f", "caller's full name", "f"); + QCommandLineOption aOption(QStringList() << "a", "call's app", "a"); + QCommandLineParser parser; + parser.addOption(oldPwdOption); + parser.addOption(newPwdOption); + parser.addOption(userOption); + parser.addOption(fOption); + parser.addOption(aOption); + parser.process(a); + + + int old_file_id = -1; + int new_file_id = -1; + if (parser.isSet(oldPwdOption)) { + old_file_id = parser.value(oldPwdOption).toInt(); + } + if (parser.isSet(newPwdOption)) { + new_file_id = parser.value(newPwdOption).toInt(); + } + Manager manager(old_file_id, new_file_id); + manager.start(); + + std::signal(SIGTERM, Manager::exit); + std::signal(SIGKILL, Manager::exit); + + return a.exec(); +} diff --git a/plugins/login-gesture/resetDialog/resetdialog.qrc b/plugins/login-gesture/resetDialog/resetdialog.qrc new file mode 100644 index 00000000..388fff89 --- /dev/null +++ b/plugins/login-gesture/resetDialog/resetdialog.qrc @@ -0,0 +1,5 @@ + + + success.svg + + diff --git a/plugins/login-gesture/resetDialog/resetpatterncontroller.cpp b/plugins/login-gesture/resetDialog/resetpatterncontroller.cpp new file mode 100644 index 00000000..e449174e --- /dev/null +++ b/plugins/login-gesture/resetDialog/resetpatterncontroller.cpp @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "resetpatterncontroller.h" +#include "gestureauthworker.h" +#include "gesturemodifyworker.h" +#include "waypointmodel.h" +#include "translastiondoc.h" + +#include +#include + +using namespace gestureLogin; +using namespace gestureSetting; + +ResetPatternController::ResetPatternController(QObject *parent) + : QObject(parent) + , m_fileId(0) + , m_file(new QFile(this)) + , m_authWorker(new gestureLogin::GestureAuthWorker(this)) + , m_modifyWorker(new gestureSetting::GestureModifyWorker(this)) +{ + initConnection(); +} + +ResetPatternController::~ResetPatternController() +{ +} + +void ResetPatternController::setOldPasswordFileId(int fileId) +{ + QFile file; + if (!file.open(fileId, QFile::ReadOnly)) { + qWarning() << "Failed to open file for writing, fileId:" << fileId; + return; + } + m_localPassword = file.readLine(); + // 需要去掉后面的\n,否则无法校验通过 + m_localPassword = m_localPassword.trimmed(); + m_authWorker->setLocalPassword(m_localPassword); +} + +void ResetPatternController::setNewPasswordFileId(int fileId) +{ + m_fileId = fileId; +} + +void ResetPatternController::start() +{ + auto *wayPointModel = WayPointModel::instance(); + + if (m_localPassword.isEmpty()) { + // 如果本地密码为空,则不进入校验阶段,直接请求密码 + wayPointModel->setCurrentMode(Mode::Enroll); + m_modifyWorker->setActive(true); + } else { + // 如果本地密码不为空,则先进行本地密码校验 + wayPointModel->setCurrentMode(Mode::Auth); + m_authWorker->setActive(true); + } +} + +void ResetPatternController::close() +{ + if (m_file->isOpen()) { + m_file->close(); + } +} + +void ResetPatternController::initConnection() +{ + auto *wayPointModel = WayPointModel::instance(); + + connect(wayPointModel, &WayPointModel::authDone, this, [this, wayPointModel] { + // 如果当前是重置密码模式,不做任何处理 + if (wayPointModel->currentMode() == Mode::Enroll) + return; + + // 停止认证的worker + m_authWorker->setActive(false); + // 密码验证通过后,设置当前为重置密码模式 + wayPointModel->setCurrentMode(Mode::Enroll); + // 进入设置密码页面后,设置标题和提示内容 + m_modifyWorker->setActive(true); + }); + + connect(m_modifyWorker, &GestureModifyWorker::inputFinished, this, &ResetPatternController::inputFinished); + connect(m_modifyWorker, &GestureModifyWorker::requestSaveToken, this, &ResetPatternController::onSaveToken); +} + +void ResetPatternController::onSaveToken(const QString &token) +{ + // 向父进程写入token + if (m_file->isOpen()) + m_file->close(); + + if (!m_file->open(m_fileId, QFile::WriteOnly)) { + qWarning() << "Failed to open file for writing, fileId:" << m_fileId; + return; + } + + qDebug() << "Writing token"; + QByteArray tmpData = QString("%1\n").arg(token).toLocal8Bit(); + m_file->write(tmpData, tmpData.length()); +} diff --git a/plugins/login-gesture/resetDialog/resetpatterncontroller.h b/plugins/login-gesture/resetDialog/resetpatterncontroller.h new file mode 100644 index 00000000..20ae4dba --- /dev/null +++ b/plugins/login-gesture/resetDialog/resetpatterncontroller.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RESETPATTERNCONTROLLER_H +#define RESETPATTERNCONTROLLER_H + +#include + +class QFile; + +namespace gestureLogin { +class GestureAuthWorker; +} + +namespace gestureSetting { +class GestureModifyWorker; +} + +class ResetPatternController : public QObject +{ + Q_OBJECT + +public: + explicit ResetPatternController(QObject *parent = nullptr); + ~ResetPatternController() override; + void setOldPasswordFileId(int fileId); + void setNewPasswordFileId(int fileId); + void start(); + void close(); + +signals: + void inputFinished(); // 第二次输入token合法并完成 + +private: + void initConnection(); + +private slots: + void onSaveToken(const QString &token); + +private: + int m_fileId; + QString m_localPassword; + QFile *m_file; + gestureLogin::GestureAuthWorker *m_authWorker; + gestureSetting::GestureModifyWorker *m_modifyWorker; +}; + +#endif // RESETPATTERNCONTROLLER_H diff --git a/plugins/login-gesture/resetDialog/success.svg b/plugins/login-gesture/resetDialog/success.svg new file mode 100644 index 00000000..3e5e1461 --- /dev/null +++ b/plugins/login-gesture/resetDialog/success.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/plugins/login-gesture/src/gestureauthworker.cpp b/plugins/login-gesture/src/gestureauthworker.cpp new file mode 100644 index 00000000..a905780b --- /dev/null +++ b/plugins/login-gesture/src/gestureauthworker.cpp @@ -0,0 +1,260 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gestureauthworker.h" +#include "waypointmodel.h" +#include "login_module_interface_v2.h" +#include "translastiondoc.h" +#include "tokenCrypt.h" + +#include + +using namespace gestureLogin; + +// 负责手势认证过程 +GestureAuthWorker::GestureAuthWorker(QObject *parent) + : QObject(parent) + , m_userService(nullptr) + , m_stateMachine(nullptr) + +{ + m_unLockTimer.setSingleShot(true); + m_remaindTimer.setSingleShot(false); + m_remaindTimer.setInterval(1000 * 60); + + initConnection(); +} + +void GestureAuthWorker::setLocalPassword(const QString &localPassword) +{ + m_localPasswd = localPassword; +} + +bool GestureAuthWorker::gestureEnabled() +{ + return true; +} + +bool GestureAuthWorker::gestureExist() +{ + return true; +} + +void GestureAuthWorker::setActive(bool active) +{ + if (active) { + initState(); + } else { + if (m_stateMachine) { + m_stateMachine->stop(); + m_stateMachine->deleteLater(); + m_stateMachine = nullptr; + } + } +} + +void GestureAuthWorker::initConnection() +{ + WayPointModel *model = WayPointModel::instance(); + connect(model, &WayPointModel::gestureStateChanged, this, [this, model](int state) { + if (model->appType() == ModelAppType::LoginLock) { + bool enrolled = state == GestureState::Set; + setActive(enrolled); + model->setCurrentMode(enrolled ? Mode::Auth : Mode::Enroll); + } + }); + + // 只处理认证过程 + connect(model, &WayPointModel::pathDone, this, [this, model] { + // 仅处理认证过程 + auto mode = model->currentMode(); + auto type = model->appType(); + if (mode == Mode::Auth) { + // 在登录锁屏上解锁 + if (type == ModelAppType::LoginLock) { + qDebug() << "worker send token"; + Q_EMIT requestSendToken(model->getToken()); + } + + // 重置密码对话框上的认证是一个单纯的本地密文对比的过程 + if (type == ModelAppType::Reset) { + QString token = gestureEncrypt::cryptUserPassword(model->getToken(), m_localPasswd.toUtf8()); + // 从外部获取的密文与本地对比 + if (token == m_localPasswd) { + Q_EMIT model->authDone(); + } else { + Q_EMIT model->authError(); + } + } + } + }); +} + +void GestureAuthWorker::initState() +{ + if (m_stateMachine) { + delete m_stateMachine; + m_stateMachine = nullptr; + } + + m_stateMachine = new QStateMachine(m_stateMachine); + + auto model = WayPointModel::instance(); + auto tanslator = TranslastionDoc::instance(); + + QString startTitle = tanslator->getDoc(model->appType() == ModelAppType::Reset ? DocIndex::ModifyPasswd : DocIndex::LoginStart); + + // 开始认证 + auto startState = new QState(m_stateMachine); + startState->assignProperty(model, "title", startTitle); + startState->assignProperty(model, "tip", tanslator->getDoc(model->appType() == ModelAppType::Reset ? DocIndex::DrawCurrentPasswd : DocIndex::RequestDrawing)); + // 认证失败,需要更新锁定时间与错误次数 + auto authError = new QState(m_stateMachine); + auto authErrTip = model->errorTextStyle().arg(tanslator->getDoc(DocIndex::AuthErrorWithTimes)); + switch (model->appType()) { + case ModelAppType::LoginLock: + // authError->assignProperty(model, "title", tanslator->getDoc(DocIndex::LoginStart)); + // authError->assignProperty(model, "tip", authErrTip); + break; + case ModelAppType::Reset: + authError->assignProperty(model, "title", tanslator->getDoc(DocIndex::ModifyPasswd)); + authError->assignProperty(model, "tip", tanslator->getDoc(DocIndex::ContactAdmin)); + break; + default: + break; + } + + // 输入错误提示 + auto inputError = new QState(m_stateMachine); + inputError->assignProperty(model, "title", startTitle); + auto pathErrorTip = model->errorTextStyle().arg(tanslator->getDoc(DocIndex::PathError)); + inputError->assignProperty(model, "tip", pathErrorTip); + + startState->addTransition(model, SIGNAL(pathError()), inputError); + startState->addTransition(model, SIGNAL(authError()), authError); + startState->addTransition(model, SIGNAL(authDone()), startState); + + inputError->addTransition(model, SIGNAL(authDone()), startState); + inputError->addTransition(model, SIGNAL(authError()), authError); + inputError->addTransition(model, SIGNAL(pathError()), inputError); + + authError->addTransition(model, SIGNAL(pathError()), inputError); + authError->addTransition(model, SIGNAL(authDone()), startState); + authError->addTransition(model, SIGNAL(authError()), authError); + + m_stateMachine->setInitialState(startState); + m_stateMachine->start(); +} + +void GestureAuthWorker::onAuthStateChanged(int authType, int authState) +{ + using dss::module::AuthType; + using dss::module::AuthState; + + if (WayPointModel::instance()->currentMode() != Mode::Auth) { + return; + } + + if (authType == AuthType::AT_All && authState == AuthState::AS_Success) { + Q_EMIT WayPointModel::instance()->authDone(); + } + + if (authType != AuthType::AT_Pattern) { + return; + } + + switch (authState) { + case AuthState::AS_Success: + Q_EMIT WayPointModel::instance()->authDone(); + break; + case AuthState::AS_Failure: + Q_EMIT WayPointModel::instance()->authError(); + break; + case AuthState::AS_Locked: + // 认证发送的lock状态,代表当前认证锁定 + WayPointModel::instance()->setLocked(true); + break; + case AuthState::AS_Unlocked: + // 认证发送的unlock,代表当前认证解锁 + WayPointModel::instance()->setLocked(false); + break; + case AuthState::AS_Started: + // 插件框架响应的计时器重置认证,代表当前认证解锁 + WayPointModel::instance()->setLocked(false); + break; + default: + break; + } +} + +// 这里只处理UI响应,model的状态设置交给authStatus控制 +void GestureAuthWorker::onLimitsInfoChanged(bool locked, int maxTries, int numFailures, int unlockSecs, const QString &unlockTime) +{ + auto model = WayPointModel::instance(); + if (model->currentMode() != Mode::Auth) { + return; + } + + do { + auto translator = TranslastionDoc::instance(); + // 未锁定状态 + if (numFailures && maxTries && numFailures < maxTries && !unlockSecs) { + uint remains = static_cast(maxTries - numFailures); + auto remainStr = model->errorTextStyle().arg(translator->getDoc(DocIndex::AuthErrorWithTimes).arg(remains)); + model->setProperty("tip", remainStr); + break; + } + + m_unLockTimer.stop(); + m_unLockTimer.disconnect(); + + m_remaindTimer.stop(); + m_remaindTimer.disconnect(); + + model->setProperty("title", TranslastionDoc::instance()->getDoc(DocIndex::LoginStart)); + model->setProperty("tip", TranslastionDoc::instance()->getDoc(DocIndex::RequestDrawing)); + + // unlockSecs 是唯一判断条件 + if (unlockSecs) { + qDebug() << "input should be locked from limit info content"; + // 显示锁定时间 + uint intervalSeconds = QDateTime::fromString(unlockTime, Qt::ISODateWithMs).toLocalTime().toSecsSinceEpoch() + - QDateTime::currentDateTimeUtc().toSecsSinceEpoch(); + // 每次设置时,强制更新计时器 + m_unLockTimer.setInterval(static_cast(intervalSeconds) * 1000); + connect(&m_unLockTimer, &QTimer::timeout, this, [this] { + m_remaindTimer.stop(); + // 信号通知解除界面禁用 + auto model = WayPointModel::instance(); + model->setProperty("title", TranslastionDoc::instance()->getDoc(DocIndex::LoginStart)); + model->setProperty("tip", TranslastionDoc::instance()->getDoc(DocIndex::RequestDrawing)); + }); + + m_lockMinutes = unlockSecs / 60; + if (unlockSecs % 60) { + m_lockMinutes += 1; + } + + auto lockString = translator->getDoc(DocIndex::DeviceLock).arg(m_lockMinutes); + model->setProperty("title", lockString); + model->setProperty("tip", model->errorTextStyle().arg(translator->getDoc(DocIndex::DeviceLockHelp))); + + if (m_lockMinutes) { + connect(&m_remaindTimer, &QTimer::timeout, this, [this] { + // 更新锁定时间 + m_lockMinutes--; + if (m_lockMinutes) { + auto errStr = TranslastionDoc::instance()->getDoc(DocIndex::DeviceLock).arg(m_lockMinutes); + WayPointModel::instance()->setProperty("title", errStr); + } + }); + } + + m_remaindTimer.start(); + m_unLockTimer.start(); + + break; + } + } while (false); +} diff --git a/plugins/login-gesture/src/gestureauthworker.h b/plugins/login-gesture/src/gestureauthworker.h new file mode 100644 index 00000000..3bc25abf --- /dev/null +++ b/plugins/login-gesture/src/gestureauthworker.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef GESTUREWORKER_H +#define GESTUREWORKER_H + +#include +#include +#include +#include + +namespace gestureLogin { +class GestureAuthWorker : public QObject +{ + Q_OBJECT + +public: + GestureAuthWorker(QObject *parent = nullptr); + void setLocalPassword(const QString &localPassword); + + // 功能已开启 + bool gestureEnabled(); + + // 手势已录入 + bool gestureExist(); + + void setActive(bool); + +private: + void initConnection(); + void initState(); + +public Q_SLOTS: + void onAuthStateChanged(int, int); + void onLimitsInfoChanged(bool, int, int, int, const QString &); + +Q_SIGNALS: + void requestSendToken(const QString &); + +private: + QDBusInterface *m_userService; + QStateMachine *m_stateMachine; + QString m_localPasswd; + + int m_lockMinutes; + + QTimer m_remaindTimer; + QTimer m_unLockTimer; +}; +} // namespace gestureLogin + +#endif // GESTUREWORKER_H diff --git a/plugins/login-gesture/src/gesturemodifyworker.cpp b/plugins/login-gesture/src/gesturemodifyworker.cpp new file mode 100644 index 00000000..62171394 --- /dev/null +++ b/plugins/login-gesture/src/gesturemodifyworker.cpp @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gesturemodifyworker.h" +#include "waypointmodel.h" +#include "gestureauthworker.h" +#include "translastiondoc.h" + +using namespace gestureSetting; +using namespace gestureLogin; + +GestureModifyWorker::GestureModifyWorker(QObject *parent) + : QObject(parent) +{ + initConnect(); +} + +void GestureModifyWorker::setActive(bool active) +{ + // 无论进入还是离开这个状态都清空内部数据 + m_token = ""; + + auto *wayPointModel = WayPointModel::instance(); + auto connectType = Qt::AutoConnection | Qt::UniqueConnection; + if (active) { + connect(wayPointModel, &WayPointModel::pathError, this, &GestureModifyWorker::onPathError, Qt::ConnectionType(connectType)); + connect(wayPointModel, &WayPointModel::pathDone, this, &GestureModifyWorker::onPathDone, Qt::ConnectionType(connectType)); + wayPointModel->setProperty("title", TranslastionDoc::instance()->getDoc(DocIndex::SetPasswd)); + wayPointModel->setProperty("tip", TranslastionDoc::instance()->getDoc(DocIndex::RequestDrawing)); + } +} + +void GestureModifyWorker::onPathDone() +{ + auto *wayPointModel = WayPointModel::instance(); + + // 这里只处理录入密码的模式 + if (wayPointModel->currentMode() != Mode::Enroll) + return; + + QString token = wayPointModel->getToken(); + // 密码为空,一般是从密码验证成功后进入到当前重设密码的过程,此时无需继续 + if (token.isEmpty()) + return; + + TranslastionDoc *transDoc = TranslastionDoc::instance(); + wayPointModel->clearPath(); + + if (m_token.isEmpty()) { + m_token = token; + // 如果存储的token为空,说明是第一次设置密码成功,此时更改提示为(请重新录入手势密码) + wayPointModel->setProperty("tip", transDoc->getDoc(DocIndex::RequestDrawingAgain)); + } else if (m_token == token) { + // 如果token不为空且两次的token值相同,则认为本次校验通过 + Q_EMIT requestSaveToken(m_token); + Q_EMIT inputFinished(); + } else { + // 如果两次的token不同,回到上一次输入密码的界面来重新录入 + m_token.clear(); + // 给出提示,认为本次和上次校验不一致 + auto tip = wayPointModel->errorTextStyle().arg(transDoc->getDoc(DocIndex::Inconsistent)); + wayPointModel->setProperty("tip", tip); + // 2秒过后文案变为“请绘制手势密码” + QTimer::singleShot(2000, this, [=] { + // 请绘制手势密码 + wayPointModel->setProperty("tip", transDoc->getDoc(DocIndex::RequestDrawing)); + }); + } +} + +void GestureModifyWorker::onPathError() +{ + auto *wayPointModel = WayPointModel::instance(); + + // 这里只处理录入密码的模式 + if (wayPointModel->currentMode() != Mode::Enroll) + return; + + auto pathErrorTip = wayPointModel->errorTextStyle().arg(TranslastionDoc::instance()->getDoc(DocIndex::PathError)); + wayPointModel->setProperty("tip", pathErrorTip); + +} + +void GestureModifyWorker::initConnect() +{ + auto model = WayPointModel::instance(); + if (model->appType() == ModelAppType::LoginLock) { + connect(WayPointModel::instance(), &WayPointModel::gestureStateChanged, this, [&] (int state) { + setActive(state != GestureState::Set ? true : false); + }); + } + + connect(model, &WayPointModel::pathDone, this, &GestureModifyWorker::onPathDone); + connect(model, &WayPointModel::pathError, this, &GestureModifyWorker::onPathError); +} diff --git a/plugins/login-gesture/src/gesturemodifyworker.h b/plugins/login-gesture/src/gesturemodifyworker.h new file mode 100644 index 00000000..c6474bd7 --- /dev/null +++ b/plugins/login-gesture/src/gesturemodifyworker.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef GESTUREMODIFYWORKER_H +#define GESTUREMODIFYWORKER_H + +#include + +namespace gestureSetting { + +class GestureModifyWorker : public QObject +{ + Q_OBJECT + +public: + explicit GestureModifyWorker(QObject *parent = nullptr); + void setActive(bool active); + +signals: + void inputFinished(); // 第二次输入token合法并完成 + void requestSaveToken(const QString &token); // 请求保存token + +private slots: + void onPathDone(); + void onPathError(); + +private: + void initConnect(); + +private: + QString m_token; +}; + +} // namespace gestureSetting + +#endif // GESTUREMODIFYWORKER_H diff --git a/plugins/login-gesture/src/gesturepannel.cpp b/plugins/login-gesture/src/gesturepannel.cpp new file mode 100644 index 00000000..87b47c45 --- /dev/null +++ b/plugins/login-gesture/src/gesturepannel.cpp @@ -0,0 +1,165 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gesturepannel.h" + +#include "waypointwidget.h" +#include "waypointmodel.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace gestureLogin; + +static int itemsAccount = 9; + +GesturePannel::GesturePannel(QWidget *parent) + : QWidget(parent) + , m_pathStarted(false) +{ + setFocusPolicy(Qt::NoFocus); + setMouseTracking(true); + setFixedSize(250, 250); + setWindowFlag(Qt::FramelessWindowHint); + setAttribute(Qt::WA_TranslucentBackground); + setContentsMargins(0, 0, 0, 0); + init(); + initConnect(); +} + +void GesturePannel::init() +{ + if (!itemsAccount) { + return; + } + + qreal root = qSqrt(itemsAccount); + int column = static_cast(root); + + // 只处理N*N的排列图形 + if (itemsAccount % column != 0) { + return; + } + + int solidSpaceWidth = this->width() / column; + int fixWidth = (solidSpaceWidth - 50) / 2; + + m_itemRects.clear(); + for (int index = 0; index < itemsAccount; index++) { + auto wid = new WayPointWidget(this); + wid->setFocusPolicy(Qt::NoFocus); + wid->setId(index); + // 布局 + int x = this->contentsRect().top() + solidSpaceWidth * (index % column); + int y = this->contentsRect().left() + solidSpaceWidth * (index / column); + wid->setFixedSize(52, 52); + wid->move(x + fixWidth * (index % column), y + fixWidth * (index / column)); + m_widRects.insert(wid, wid->geometry()); + m_itemRects[index] = wid->geometry(); + + connect(WayPointModel::instance(), &WayPointModel::selected, wid, &WayPointWidget::onSelectedById); + connect(wid, &WayPointWidget::arrived, WayPointModel::instance(), &WayPointModel::onPathArrived); + connect(this, &GesturePannel::pathStarted, wid, &WayPointWidget::onPathStarted); + connect(this, &GesturePannel::pathStopped, wid, &WayPointWidget::onPathStopped); + } +} + +void GesturePannel::initConnect() +{ + connect(WayPointModel::instance(), &WayPointModel::selected, this, [this](int, bool) { + update(); + }); + connect(WayPointModel::instance(), &WayPointModel::widgetColorChanged, this, [this] { + update(); + }); + + connect(this, &GesturePannel::pathStopped, WayPointModel::instance(), &WayPointModel::onUserInputDone); + + connect(WayPointModel::instance(), &WayPointModel::inputLocked, this, &QWidget::setDisabled); + setDisabled(WayPointModel::instance()->locked()); +} + +void GesturePannel::reset() +{ +} + +void GesturePannel::mousePressEvent(QMouseEvent *event) +{ + if (!WayPointModel::instance()->locked()) { + // 起点不一定在结点上,仅记录起始点,交给mouseMove处理连接 + releaseMouse(); + // 当输入小于4个点时,将保留界面直到用户再输入 + WayPointModel::instance()->clearPath(); + m_pathStarted = true; + Q_EMIT pathStarted(event->pos()); + + m_currentPos = event->pos(); + + update(); + } + + QWidget::mousePressEvent(event); +} + +void GesturePannel::mouseReleaseEvent(QMouseEvent *event) +{ + if (!WayPointModel::instance()->locked()) { + m_pathStarted = false; + Q_EMIT pathStopped(); + + update(); + } + + QWidget::mouseReleaseEvent(event); +} + +// 最后一个结点的连接线 +void GesturePannel::mouseMoveEvent(QMouseEvent *event) +{ + if (m_pathStarted) { + m_currentPos = event->pos(); + foreach (auto rect, m_widRects) { + if (rect.contains(m_currentPos)) { + auto wid = m_widRects.key(rect); + Q_EMIT wid->arrived(wid->id()); + } + } + update(); + } + + QWidget::mouseMoveEvent(event); +} + +// 选中点的样式变化自己去处理,这里只画连接线 +void GesturePannel::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + if (WayPointModel::instance()->currentPoints().size()) { + QVector wayPoints; + auto currentSelected = WayPointModel::instance()->currentPoints(); + foreach (auto index, currentSelected) { + wayPoints.push_back(m_itemRects.value(index).center()); + } + + if (m_pathStarted) { + wayPoints.push_back(m_currentPos); + } + + auto model = WayPointModel::instance(); + auto colorConfig = model->colorConfig(); + QColor lineColor = model->showErrorStyle() ? colorConfig.warningLine : colorConfig.line; + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + QPen pen(lineColor, 2); + painter.setPen(pen); + painter.drawPolyline(wayPoints.data(), wayPoints.size()); + } +} diff --git a/plugins/login-gesture/src/gesturepannel.h b/plugins/login-gesture/src/gesturepannel.h new file mode 100644 index 00000000..4adc72e2 --- /dev/null +++ b/plugins/login-gesture/src/gesturepannel.h @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef GESTUREPANNEL_H +#define GESTUREPANNEL_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace gestureLogin { +class WayPointWidget; + +class GesturePannel : public QWidget +{ + Q_OBJECT + +public: + explicit GesturePannel(QWidget *parent = nullptr); + + void init(); + void initConnect(); + + inline bool getStarted() const { return m_pathStarted; } + void reset(); + +Q_SIGNALS: + void pathStarted(const QPoint &); + void pathStopped(); + void gestureAuthFaile(); + void gestureAuthDone(); + + void inputError(); + void inputDone(); + + void authError(); + void authDone(); + +protected: + virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + + virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + void initPannel(); + void initConnections(); + +private: + bool m_pathStarted; + QPainterPath m_gusturePath; + QPoint m_currentPos; + QMap m_itemRects; + + QStateMachine *m_stateMachine; + QMap m_widRects; +}; +} // namespace gestureLogin +#endif // GESTUREPANNEL_H diff --git a/plugins/login-gesture/src/modulewidget.cpp b/plugins/login-gesture/src/modulewidget.cpp new file mode 100644 index 00000000..24a186ec --- /dev/null +++ b/plugins/login-gesture/src/modulewidget.cpp @@ -0,0 +1,167 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "modulewidget.h" +#include "waypointmodel.h" +#include "translastiondoc.h" + +#include +#include + +#include +#include +#include + +using namespace gestureLogin; + +// 文案、图片与按钮 +// 考虑到 +ModuleWidget::ModuleWidget(QWidget *parent) + : QWidget(parent) + , m_title(nullptr) + , m_tip(nullptr) + , m_firstEnroll(nullptr) + , m_mainLayout(nullptr) + , m_startEnrollBtn(nullptr) + , m_inputWid(nullptr) + , m_layout(nullptr) +{ + this->setContentsMargins(0, 0, 0, 0); + + init(); + initConnection(); +} + +void ModuleWidget::reset() +{ +} + +void ModuleWidget::init() +{ + DGUI_USE_NAMESPACE + + auto model = WayPointModel::instance(); + m_title = new DLabel; + m_title->setFixedHeight(35); + + m_tip = new DTipLabel; + if (model->appType() == ModelAppType::LoginLock) { + m_tip->setForegroundRole(QPalette::ColorRole::Light); + } + + m_tip->setFixedHeight(26); + m_startEnrollBtn = new DPushButton; + m_startEnrollBtn->setFixedSize(200, 54); + + m_title->setVisible(false); + m_tip->setVisible(false); + m_startEnrollBtn->setVisible(false); + + DFontSizeManager::instance()->bind(m_title, DFontSizeManager::T3); + DFontSizeManager::instance()->bind(m_tip, DFontSizeManager::T5); + + m_iconLabel = new DLabel; + m_iconLabel->setVisible(false); + + m_inputWid = new GesturePannel; + m_inputWid->setVisible(false); + + m_layout = new QVBoxLayout; + this->setLayout(m_layout); + + if (model->getGestureState() == GestureState::NotSet && model->appType() == ModelAppType::LoginLock) { + showFirstEnroll(); + } else { + showUserInput(); + } +} + +void ModuleWidget::initConnection() +{ + auto model = WayPointModel::instance(); + + connect(model, &WayPointModel::titleChanged, m_title, [&](const QString &text) { + m_title->setVisible(true); + m_title->setEnabled(true); + m_title->setText(text); + }); + connect(model, &WayPointModel::tipChanged, m_tip, [&](const QString &text) { + m_tip->setVisible(true); + m_tip->setEnabled(true); + m_tip->setText(text); + }); +} + +void ModuleWidget::showFirstEnroll() +{ + DWIDGET_USE_NAMESPACE + + int count = m_layout->count(); + if (count) { + while (count != -1) { + m_layout->takeAt(--count); + } + } + + // 首次录入的布局 + m_layout->addStretch(50); + m_layout->addWidget(m_title, 0, Qt::AlignCenter); + m_layout->addSpacing(10); + m_layout->addWidget(m_tip, 0, Qt::AlignCenter); + m_layout->addSpacing(60); + + QPixmap iconPix = DHiDPIHelper::loadNxPixmap(":/icons/firstEnroll.svg"); + auto scaledPixmap = iconPix.scaled(120, 120, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + m_iconLabel->setPixmap(scaledPixmap); + m_layout->addWidget(m_iconLabel, 0, Qt::AlignCenter); + m_layout->addSpacing(130); + + m_layout->addWidget(m_startEnrollBtn, 0, Qt::AlignCenter); + + m_title->setVisible(true); + m_tip->setVisible(true); + m_startEnrollBtn->setVisible(true); + m_iconLabel->setVisible(true); + + m_layout->addStretch(100); + + // 固定文本,不参与动态变化 + auto trans = TranslastionDoc::instance(); + m_title->setText(trans->getDoc(DocIndex::Enabled)); + m_tip->setText(trans->getDoc(DocIndex::RequestFirstEnroll)); + m_startEnrollBtn->setText(trans->getDoc(DocIndex::SetPasswd)); + + connect(m_startEnrollBtn, &DPushButton::clicked, this, [this] { + showUserInput(); + }); +} + +void ModuleWidget::showUserInput() +{ + int count = m_layout->count(); + if (count) { + while (count != -1) { + m_layout->takeAt(--count); + } + } + + m_startEnrollBtn->setVisible(false); + m_iconLabel->setVisible(false); + + m_layout->setAlignment(Qt::AlignCenter); + m_layout->addWidget(m_title, 0, Qt::AlignCenter); + m_layout->addSpacing(10); + m_layout->addWidget(m_tip, 0, Qt::AlignCenter); + m_layout->addSpacing(40); + m_layout->addWidget(m_inputWid, 0, Qt::AlignCenter); + + m_title->setVisible(true); + m_tip->setVisible(true); + m_inputWid->setVisible(true); + + m_title->setText(WayPointModel::instance()->title()); + m_tip->setText(WayPointModel::instance()->tip()); + + m_layout->addStretch(100); +} diff --git a/plugins/login-gesture/src/modulewidget.h b/plugins/login-gesture/src/modulewidget.h new file mode 100644 index 00000000..bfa91218 --- /dev/null +++ b/plugins/login-gesture/src/modulewidget.h @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGINWIDGET_H +#define LOGINWIDGET_H + +#include "gesturepannel.h" + +#include +#include +#include + +#include +#include + +DWIDGET_USE_NAMESPACE + +namespace gestureLogin { +class ModuleWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ModuleWidget(QWidget *parent = nullptr); + void reset(); + +public Q_SLOTS: + void showUserInput(); + +private: + void init(); + void initConnection(); + void showFirstEnroll(); // 登录锁屏上首次设置 + +private: + // 大标题与小标题 + DLabel *m_title; + DLabel *m_tip; + QLayout *m_firstEnroll; + QLayout *m_mainLayout; + DPushButton *m_startEnrollBtn; + DLabel *m_iconLabel; + GesturePannel *m_inputWid; + QVBoxLayout *m_layout; +}; +} // namespace gestureLogin +#endif // LOGINWIDGET_H diff --git a/plugins/login-gesture/src/waypointmodel.cpp b/plugins/login-gesture/src/waypointmodel.cpp new file mode 100644 index 00000000..98ae22e4 --- /dev/null +++ b/plugins/login-gesture/src/waypointmodel.cpp @@ -0,0 +1,367 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "waypointmodel.h" +#include "tokenCrypt.h" + +#include +#include + +using namespace gestureLogin; + +// 明文内容字典 +const QMap kContent = {{0, "0"}, + {1, "1"}, + {2, "2"}, + {3, "3"}, + {4, "4"}, + {5, "5"}, + {6, "6"}, + {7, "7"}, + {8, "8"}}; + +WayPointModel::WayPointModel(QObject *parent) + : QObject(parent) + , m_size(9) // 3 * 3, 如果有需求,改从配置获取 + , m_currentMode(Mode::Auth) + , m_gestureStateFlag(-1) + , m_gestureEnable(false) + , m_showErrorStyle(false) + , m_locked(false) + , m_localeName("") +{ + initColorConfig(); + connect(this, &WayPointModel::authDone, this, &WayPointModel::clearPath); + connect(this, &WayPointModel::authError, this, &WayPointModel::clearPath); +} + +WayPointModel *WayPointModel::instance() +{ + static WayPointModel model; + return &model; +} + +const QList &WayPointModel::currentPoints() +{ + return m_selectedPoints; +} + +ModelAppType WayPointModel::appType() const +{ + auto name = QApplication::applicationName(); + if (name.contains("lock", Qt::CaseInsensitive) || name.contains("greeter", Qt::CaseInsensitive)) { + return ModelAppType::LoginLock; + } + + if (name.contains("reset", Qt::CaseInsensitive)) { + return ModelAppType::Reset; + } + + return ModelAppType::Unknow; +} + +bool WayPointModel::isLockApp() +{ + return QApplication::applicationName().contains("lock", Qt::CaseInsensitive); +} + +// 通过回调到查询 +bool WayPointModel::isGestureEnabled() +{ + return m_gestureEnable; +} + +const GestureColors &WayPointModel::colorConfig() +{ + return m_colorConfig; +} + +QString WayPointModel::errorTextStyle() const +{ + return "%1"; +} + +void WayPointModel::setLocaleName(const QString &locale) +{ + auto content = locale.split("."); + if (content.size()) { + auto name = content[0]; + if (m_localeName != name) { + m_localeName = name; + Q_EMIT localeChanged(m_localeName); + } + } +} + +void WayPointModel::initColorConfig() +{ + DGUI_USE_NAMESPACE; + // 登录锁屏样式无大变化 + if (appType() == ModelAppType::LoginLock) { + setColorByTheme(DGuiApplicationHelper::UnknownType); + } else { + // 对话框上存在明暗样式 + auto themeType = DGuiApplicationHelper::instance()->themeType(); + setColorByTheme(themeType); + + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [&] (DGuiApplicationHelper::ColorType t) { + setColorByTheme(t); + Q_EMIT widgetColorChanged(); + }); + } +} + +void WayPointModel::setColorByTheme(int type) +{ + DGUI_USE_NAMESPACE; + switch (type) { + case DGuiApplicationHelper::LightType: + m_colorConfig.line.setRgb(0, 129, 255); + m_colorConfig.unSelecteBoarder.setRgb(0, 0, 0, 0.3 * 255); + m_colorConfig.selectedBoarder.setRgb(0, 129, 255); + m_colorConfig.fill.setRgb(0, 129, 255, 0.1 * 255); + m_colorConfig.internalFill.setRgb(0, 129, 255); + m_colorConfig.warningFill.setRgb(255, 87, 54, 0.1 * 255); + m_colorConfig.warningLine.setRgb(255, 87, 54); + break; + case DGuiApplicationHelper::DarkType: + m_colorConfig.line.setRgb(0, 129, 255); + m_colorConfig.unSelecteBoarder.setRgb(255, 255, 255, 0.3 * 255); + m_colorConfig.selectedBoarder.setRgb(0, 129, 255); + m_colorConfig.fill.setRgb(0, 129, 255, 0.1 * 255); + m_colorConfig.internalFill.setRgb(0, 129, 255); + m_colorConfig.warningFill.setRgb(255, 87, 54, 0.1 * 255); + m_colorConfig.warningLine.setRgb(255, 87, 54); + break; + default: + m_colorConfig.line.setRgb(255, 255, 255); + m_colorConfig.unSelecteBoarder.setRgb(255, 255, 255, 0.74 * 255); + m_colorConfig.selectedBoarder.setRgb(255, 255, 255, 0.74 * 255); + m_colorConfig.fill.setRgb(255, 255, 255, 0.2 * 255); + m_colorConfig.internalFill.setRgb(255, 255, 255); + m_colorConfig.warningFill = m_colorConfig.fill; + m_colorConfig.warningLine = m_colorConfig.line; + break; + } +} + +QString WayPointModel::userName() const +{ + return m_userName; +} + +void WayPointModel::setUserName(const QString &name) +{ + m_userName = name; +} + +bool WayPointModel::isValidPath() const +{ + auto size = m_selectedPoints.size(); + return size >= 4; +} + +QString WayPointModel::getToken() const +{ + qDebug() << int(m_currentMode); + QString rst = ""; + foreach (auto index, m_selectedPoints) { + rst.append(kContent.value(index, "")); + } + + if (rst.isEmpty()) { + qDebug() << "skip crypt for empty input"; + return ""; + } + + if (appType() == ModelAppType::Reset && m_currentMode == Mode::Auth) + return rst; + + // 仅录入时加密,登录、解锁时由前端处理明文 + // 录入时两次需要使用相同盐值加密 + if (m_currentMode == Mode::Enroll || appType() == ModelAppType::Reset) { + static QString salt = gestureEncrypt::getSalt(); + rst = gestureEncrypt::cryptUserPassword(rst, salt.toLatin1()); + } + + return rst; +} + +Mode WayPointModel::currentMode() const +{ + return m_currentMode; +} + +void WayPointModel::setCurrentMode(Mode mode) +{ + m_currentMode = mode; + Q_EMIT modeChanged(m_currentMode); + + qDebug() << "model mode changed to:" << int(m_currentMode); +} + +void WayPointModel::setTitle(const QString &title) +{ + m_title = title; + Q_EMIT titleChanged(m_title); +} + +void WayPointModel::setTip(const QString &tip) +{ + m_tip = tip; + Q_EMIT tipChanged(m_tip); +} + +void WayPointModel::setGestureState(int flag) +{ + qDebug() << flag << m_gestureStateFlag; + if (m_gestureStateFlag != flag) { + m_gestureStateFlag = flag; + Q_EMIT gestureStateChanged(m_gestureStateFlag); + } +} + +void WayPointModel::setGestureEnabled(bool enable) +{ + m_gestureEnable = enable; +} + +int WayPointModel::getGestureState() +{ + return m_gestureStateFlag; +} + +void WayPointModel::onPathArrived(int index) +{ + if (index < 0) { + return; + } + + do { + const int current = index; + if (m_selectedPoints.contains(current)) { + // 如果索引与倒数第二个相同,代表撤消上一个选中 + if (m_selectedPoints.size() >= 2) { + if (m_selectedPoints.indexOf(current) == m_selectedPoints.size() - 2) { + // 先发信号再移除,注意顺序 + Q_EMIT selected(m_selectedPoints.last(), false); + m_selectedPoints.removeLast(); + + Q_EMIT dataChanged(); + } + } + break; + } + + // 不包含,判断是否有途经的点并优先插入 + if (!m_selectedPoints.size()) { + appendPath(current); + break; + } + + if (m_selectedPoints.size()) { + // 选中所有沿途点 + int currentX = current % 3; + int currentY = current / 3; + + auto last = m_selectedPoints.last(); + int lastX = last % 3; + int lastY = last / 3; + + auto step = (current - last) / qAbs(current - last); + + auto insertPassby = [&](int dx, int dy) { + auto passByX = lastX + dx; + auto passByY = lastY + dy; + + while (passByY != currentY || passByX != currentX) { + int passbyIndex = positionToIndex(passByX, passByY); + if (passbyIndex >= 0) { + appendPath(passbyIndex); + } + passByX += dx; + passByY += dy; + } + }; + + if (currentX == lastX) { + // 同列 + insertPassby(0, step); + } else if (currentY == lastY) { + // 同行 + insertPassby(step, 0); + } else if (qAbs(currentX - lastX) == qAbs(currentY - lastY)) { + // 同斜率 + auto stepX = (currentX - lastX) / qAbs(currentX - lastX); + auto stepY = (currentY - lastY) / qAbs(currentY - lastY); + insertPassby(stepX, stepY); + } + + // 插入路过的点后,判断当前点是否在期望的路径上 + last = m_selectedPoints.last(); + lastX = last % 3; + lastY = last / 3; + if (currentX == lastX || currentY == lastY || qAbs(currentX - lastX) == qAbs(currentY - lastY)) { + appendPath(current); + } + } + + } while (false); +} + +void WayPointModel::onUserInputDone() +{ + if (m_selectedPoints.size() < 4 || m_selectedPoints.size() > 9) { + m_showErrorStyle = true; + clearPath(); + Q_EMIT pathError(); + } else { + Q_EMIT pathDone(); + } +} + +void WayPointModel::clearPath() +{ + m_selectedPoints.clear(); + Q_EMIT selected(-1, false); // 清空所有结点 + Q_EMIT dataChanged(); + + m_showErrorStyle = false; +} + +void WayPointModel::setLocked(bool locked) +{ + if (m_locked != locked) { + m_locked = locked; + Q_EMIT inputLocked(m_locked); + } +} + +int WayPointModel::positionToIndex(int x, int y) +{ + if (x < 0 || y < 0) { + return -1; + } + + int index = static_cast(m_size) - 1; + while (index >= 0) { + int ix = index % 3; + int iy = index / 3; + if (ix == x && iy == y) { + return index; + } + + index--; + } + return -1; +} + +void WayPointModel::appendPath(int index) +{ + if (!m_selectedPoints.contains(index)) { + m_selectedPoints.push_back(index); + Q_EMIT selected(index, true); + Q_EMIT dataChanged(); + } +} diff --git a/plugins/login-gesture/src/waypointmodel.h b/plugins/login-gesture/src/waypointmodel.h new file mode 100644 index 00000000..9ab18c19 --- /dev/null +++ b/plugins/login-gesture/src/waypointmodel.h @@ -0,0 +1,146 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WAYPOINTMODEL_H +#define WAYPOINTMODEL_H + +#include +#include +#include + +namespace gestureLogin { + +enum GestureState { + NotSet, + SetAndRemoved, + Set +}; + +enum class Mode { + Enroll, + Auth +}; + +enum class ModelAppType { + LoginLock, + Reset, + Unknow +}; + +struct GestureColors { + QColor line; + QColor unSelecteBoarder; + QColor selectedBoarder; + QColor fill; + QColor internalFill; + QColor warningFill; + QColor warningLine; +}; + +class WayPointModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString title MEMBER m_title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(QString tip MEMBER m_tip WRITE setTip NOTIFY tipChanged) + +public: + static WayPointModel *instance(); + const QList ¤tPoints(); + + ModelAppType appType() const; + bool isLockApp(); + + // 响应userSwitch,重置校验过程与状态 + // 通过用户名查询user的dbuspath + QString userName() const; + void setUserName(const QString &); + + inline uint size() const { return m_size; } + + bool isValidPath() const; + QString getToken() const; + + Mode currentMode() const; + void setCurrentMode(Mode); + + void setTitle(const QString &); + void setTip(const QString &); + + inline QString title() const { return m_title; } + inline QString tip() const { return m_tip; } + inline bool locked() const { return m_locked; } + + void setGestureState(int); + void setGestureEnabled(bool); + + int getGestureState(); + bool isGestureEnabled(); + + inline bool showErrorStyle() { return m_showErrorStyle; } + const GestureColors& colorConfig(); + + QString errorTextStyle() const; + + void setLocaleName(const QString &); + inline QString localeName() const { return m_localeName; } + +public Q_SLOTS: + void onPathArrived(int); + void onUserInputDone(); + void clearPath(); + void setLocked(bool); + +Q_SIGNALS: + void inputLocked(bool); + + // 文案控制 + void titleChanged(const QString &); + void tipChanged(const QString &); + void widgetColorChanged(); + + void modeChanged(Mode); + // 录入 + void finished(); + + void pathError(); // 不满足条件 + void pathDone(); // 满足条件 + + // 校验的信号转发 + void authError(); // 验证失败 + void authDone(); // 验证成功 + + void dataChanged(); // 通知UI执行更新 + void selected(int, bool); // 单个点被选中或取消 + + void gestureStateChanged(int); + void localeChanged(const QString &); + +private: + explicit WayPointModel(QObject *parent = nullptr); + int positionToIndex(int, int); + void appendPath(int); + void removePath(int); + void initColorConfig(); + void setColorByTheme(int); + +private: + QList m_selectedPoints; + uint m_size; + Mode m_currentMode; + + QString m_userName; + QString m_title; + QString m_tip; + // 后端手势标志: 0 从未录入 1 已被重置 2 已录入 + int m_gestureStateFlag; + bool m_gestureEnable; + bool m_showErrorStyle; + GestureColors m_colorConfig; + bool m_locked; + QString m_localeName; +}; +} // namespace gestureLogin + +#endif // WAYPOINTMODEL_H diff --git a/plugins/login-gesture/src/waypointwidget.cpp b/plugins/login-gesture/src/waypointwidget.cpp new file mode 100644 index 00000000..7867b0d3 --- /dev/null +++ b/plugins/login-gesture/src/waypointwidget.cpp @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "waypointwidget.h" +#include "waypointmodel.h" + +#include +#include +#include + +using namespace gestureLogin; +WayPointWidget::WayPointWidget(QWidget *parent) + : QWidget(parent) + , m_isSelected(false) +{ + setContentsMargins(0, 0, 0, 0); + + setWindowFlag(Qt::FramelessWindowHint); + setAttribute(Qt::WA_TranslucentBackground); + + connect(WayPointModel::instance(), &WayPointModel::widgetColorChanged, this, [this] { + update(); + }); +} + +void WayPointWidget::setId(int id) +{ + m_id = id; +} + +void WayPointWidget::onSelectedById(int id, bool selected) +{ + if (id == m_id || id == -1) { + m_isSelected = selected; + update(); + } +} + +void WayPointWidget::onPathStarted(const QPoint &startPoint) +{ + if (geometry().contains(startPoint)) { + Q_EMIT arrived(this->m_id); + } + + m_started = true; +} + +void WayPointWidget::onPathStopped() +{ + m_started = false; +} + +void WayPointWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainterPath pathBound; + QPainterPath pathCenter; + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + static auto model = WayPointModel::instance(); + auto colorConfig = model->colorConfig(); + + QColor unselectedBoarderColor = colorConfig.unSelecteBoarder; + QColor selectedBoarderColor = colorConfig.selectedBoarder; + QColor fillColor = colorConfig.fill; + QColor internalFillColor = colorConfig.internalFill; + + if (model->showErrorStyle()) { + selectedBoarderColor = colorConfig.warningLine; + fillColor = colorConfig.warningFill; + internalFillColor = selectedBoarderColor; + } + + pathBound.addEllipse(this->contentsRect().center(), 23, 23); + QPen pen; + pen.setColor(m_isSelected ? selectedBoarderColor : unselectedBoarderColor); + pen.setWidth(2); + painter.setPen(pen); + + if (m_isSelected) { + painter.setBrush(fillColor); + } + painter.drawPath(pathBound); + + if (m_isSelected) { + pathCenter.addEllipse(this->contentsRect().center(), 12, 12); + painter.setBrush(internalFillColor); + painter.drawPath(pathCenter); + } +} diff --git a/plugins/login-gesture/src/waypointwidget.h b/plugins/login-gesture/src/waypointwidget.h new file mode 100644 index 00000000..88d436f4 --- /dev/null +++ b/plugins/login-gesture/src/waypointwidget.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef WAYPOINTWIDGET_H +#define WAYPOINTWIDGET_H + +#include + +namespace gestureLogin { + +class WayPointWidget : public QWidget +{ + Q_OBJECT +public: + explicit WayPointWidget(QWidget *parent = nullptr); + static QList getCrossedNode(int startId, int stopId); + + void setId(int); + inline int id() { return m_id; } + +public Q_SLOTS: + void onSelectedById(int m_id, bool arrived); // 选中、撤消图形变化 + void onPathStarted(const QPoint &); + void onPathStopped(); + +Q_SIGNALS: + void arrived(int m_id); // 通知模型处理,如果可选中,再调用onSelectedById + +protected: + virtual void paintEvent(QPaintEvent *event) override; + +private: + QString m_iconPath; + int m_id; + bool m_isSelected; + bool m_started; +}; +} // namespace gestureLogin + +#endif // WAYPOINTWIDGET_H diff --git a/plugins/login-gesture/translate_generation.sh b/plugins/login-gesture/translate_generation.sh new file mode 100755 index 00000000..c9080923 --- /dev/null +++ b/plugins/login-gesture/translate_generation.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# this file is used to auto-generate .qm file from .ts file. +# author: shibowen at linuxdeepin.com + +ts_list=(`ls translations/*.ts`) + +for ts in "${ts_list[@]}" +do + printf "\nprocess ${ts}\n" + lrelease "${ts}" +done diff --git a/plugins/login-gesture/translations/login-gesture_ar.ts b/plugins/login-gesture/translations/login-gesture_ar.ts new file mode 100644 index 00000000..96b9b460 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_ar.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + تمكين كلمة مرور الإيماءة + + + For first time use, please set the gesture password first + لاستخدامها لأول مرة، يرجى تعيين كلمة مرور الإيماءة أولاً + + + Set gesture password + تعيين كلمة مرور الإيماءة + + + Please draw a gesture password + يرجى رسم كلمة مرور الإيماءة + + + Please draw the gesture password again + يرجى إعادة رسم كلمة مرور الإيماءة + + + Setup completed Start login + اكتمل الإعداد ابدأ تسجيل الدخول + + + Forgot gesture password + نسيت كلمة مرور الإيماءة + + + Sign in with gesture password + تسجيل الدخول بكلمة مرور الإيماءة + + + Gesture password has been reset + تمت إعادة تعيين كلمة مرور الإيماءة + + + Please reset the gesture password + يرجى إعادة تعيين كلمة مرور الإيماءة + + + Inconsistent with the last drawing, please redraw + غير متطابق مع الرسم الأخير، يرجى إعادة الرسم + + + Device is locked, unlocked after %1 minutes + الجهاز مقفل، سيتم إلغاء القفل بعد %1 دقيقة + + + Modify gesture password + تعديل كلمة مرور الإيماءة + + + Please draw the current gesture password + يرجى رسم كلمة مرور الإيماءة الحالية + + + Modified successfully + تم التعديل بنجاح + + + Drawing error, Contact the administrator to reset + خطأ في الرسم، اتصل بالمسؤول لإعادة التعيين + + + Cancel + إلغاء + + + Ok + موافق + + + Drawing error, %1 chances left. Contact the administrator to reset + خطأ في الرسم، تبقى %1 محاولات. اتصل بالمسؤول لإعادة التعيين + + + Setup completed Start unlock + اكتمل الإعداد ابدأ إلغاء القفل + + + Unlock with gesture password + إلغاء القفل بكلمة مرور الإيماءة + + + Minimum 4 points, please redraw + الحد الأدنى 4 نقاط، يرجى إعادة الرسم + + + Contact the administrator to reset + اتصل بالمسؤول لإعادة التعيين + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_ca.ts b/plugins/login-gesture/translations/login-gesture_ca.ts new file mode 100644 index 00000000..75bff7e3 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_ca.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + La contrasenya de gest està activada. + + + For first time use, please set the gesture password first + Per al primer ús, establiu primer la contrasenya de gest. + + + Set gesture password + Estableix la contrasenya de gest + + + Please draw a gesture password + Si us plau, dibuixeu una contrasenya de gest. + + + Please draw the gesture password again + Torneu a dibuixar la contrasenya de gest. + + + Setup completed Start login + Configuració completada. Inicieu la sessió. + + + Forgot gesture password + He oblidat la contrasenya de gest. + + + Sign in with gesture password + Inicieu la sessió amb la contrasenya de gest. + + + Gesture password has been reset + S'ha restablert la contrasenya de gest. + + + Please reset the gesture password + Si us plau, restabliu la contrasenya de gest. + + + Inconsistent with the last drawing, please redraw + Incompatible amb l'últim dibuix. Si us plau, torneu-lo a fer. + + + Device is locked, unlocked after %1 minutes + El dispositiu està bloquejat, es desbloquejarà després de %1 minuts + + + Modify gesture password + Modifica la contrasenya de gest + + + Please draw the current gesture password + Si us plau, dibuixeu la contrasenya de gest actual. + + + Modified successfully + Modificació correcta + + + Drawing error, Contact the administrator to reset + Error de dibuix. Poseu-vos en contacte amb l'administrador per restablir-lo. + + + Cancel + Cancel·la + + + Ok + D'acord + + + Drawing error, %1 chances left. Contact the administrator to reset + Error de dibuix, queden %1 intents. Poseu-vos en contacte amb l'administrador per restablir-lo. + + + Setup completed Start unlock + Configuració del desbloqueig d'inici completat + + + Unlock with gesture password + Desbloqueja amb contrasenya de gest + + + Minimum 4 points, please redraw + Com a mínim 4 punts. Torneu a fer el dibuix + + + Contact the administrator to reset + Poseu-vos en contacte amb l'administrador per restablir-lo. + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_de_DE.ts b/plugins/login-gesture/translations/login-gesture_de_DE.ts new file mode 100644 index 00000000..47ca59a6 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_de_DE.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Pass-Zeichen ist eingerichtet + + + For first time use, please set the gesture password first + Erstellen Sie bitte erstmalig ihr Pass-Zeichen + + + Set gesture password + Pass-Zeichen erstellen + + + Please draw a gesture password + Bitte zeichnen Sie ihr Pass-Zeichen + + + Please draw the gesture password again + Bitte zeichnen Sie erneut Ihr Pass-Zeichen + + + Setup completed Start login + Einrichten beendet, Anmelden beginnen + + + Forgot gesture password + Pass-Zeichen vergessen + + + Sign in with gesture password + Anmelden mit Pass-Zeichen + + + Gesture password has been reset + Pass-Zeichen wurde zurückgesetzt + + + Please reset the gesture password + Bitte setzen Sie das Pass-Zeichen zurück + + + Inconsistent with the last drawing, please redraw + Passt nicht zum letzten Pass-Zeichen, bitte nochmals zeichnen + + + Device is locked, unlocked after %1 minutes + + + + Modify gesture password + Ändern Sie das Pass-Zeichen ab + + + Please draw the current gesture password + Bitte zeichnen Sie das aktuelle Pass-Zeichen + + + Modified successfully + Erfolgreich abgeändert + + + Drawing error, Contact the administrator to reset + + + + Cancel + + + + Ok + + + + Drawing error, %1 chances left. Contact the administrator to reset + + + + Setup completed Start unlock + + + + Unlock with gesture password + + + + Minimum 4 points, please redraw + + + + Contact the administrator to reset + + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_en.ts b/plugins/login-gesture/translations/login-gesture_en.ts new file mode 100644 index 00000000..129d47b6 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_en.ts @@ -0,0 +1,99 @@ + + + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + + + + For first time use, please set the gesture password first + + + + Set gesture password + + + + Please draw a gesture password + + + + Please draw the gesture password again + + + + Setup completed Start login + + + + Forgot gesture password + + + + Sign in with gesture password + + + + Gesture password has been reset + + + + Please reset the gesture password + + + + Inconsistent with the last drawing, please redraw + + + + Device is locked, unlocked after %1 minutes + + + + Modify gesture password + + + + Please draw the current gesture password + + + + Modified successfully + + + + Drawing error, Contact the administrator to reset + + + + Cancel + + + + Ok + + + + Drawing error, %1 chances left. Contact the administrator to reset + + + + Setup completed Start unlock + + + + Unlock with gesture password + + + + Minimum 4 points, please redraw + + + + Contact the administrator to reset + + + + diff --git a/plugins/login-gesture/translations/login-gesture_es.ts b/plugins/login-gesture/translations/login-gesture_es.ts new file mode 100644 index 00000000..9f3621d6 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_es.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + La contraseña por gestos está activada + + + For first time use, please set the gesture password first + Para el primer uso, configure antes la contraseña por gestos + + + Set gesture password + Establecer contraseña por gestos + + + Please draw a gesture password + Por favor, dibuje una contraseña de gestos + + + Please draw the gesture password again + Por favor, vuelva a dibujar la contraseña del gesto + + + Setup completed Start login + Configuración completada Iniciar sesión + + + Forgot gesture password + Olvidar contraseña por gestos + + + Sign in with gesture password + Iniciar sesión con contraseña por gestos + + + Gesture password has been reset + La contraseña por gestos se ha restablecido + + + Please reset the gesture password + Restablezca la contraseña por gestos + + + Inconsistent with the last drawing, please redraw + Inconsistente con el último dibujo, vuelva a dibujarla. + + + Device is locked, unlocked after %1 minutes + El dispositivo está bloqueado, se desbloqueará después de %1 minutos. + + + Modify gesture password + Modificar contraseña por gestos + + + Please draw the current gesture password + Dibuje la contraseña por gestos actual + + + Modified successfully + Modificada exitosamente + + + Drawing error, Contact the administrator to reset + Patrón incorrecto. Contacte con el administrador para restablecerlo. + + + Cancel + Cancelar + + + Ok + Aceptar + + + Drawing error, %1 chances left. Contact the administrator to reset + Patrón incorrecto, quedan 1 oportunidad. Contacta con el administrador para reiniciar. + + + Setup completed Start unlock + Configuración completada. Iniciar desbloqueo. + + + Unlock with gesture password + Desbloquea con contraseña gestual + + + Minimum 4 points, please redraw + Mínimo 4 puntos, por favor vuelva a dibujar. + + + Contact the administrator to reset + Póngase en contacto con la administrador para restablecer + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_fi.ts b/plugins/login-gesture/translations/login-gesture_fi.ts new file mode 100644 index 00000000..de3b2992 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_fi.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Eleet salasanaksi on käytössä + + + For first time use, please set the gesture password first + Kun käytät ensimmäistä kertaa, aseta ensin ele + + + Set gesture password + Aseta ele + + + Please draw a gesture password + Piirrä ele + + + Please draw the gesture password again + Piirrä ele uudelleen + + + Setup completed Start login + Asetus valmis, aloita kirjautuminen + + + Forgot gesture password + Unohda ele + + + Sign in with gesture password + Kirjaudu sisään eleellä + + + Gesture password has been reset + Ele on nollattu + + + Please reset the gesture password + Nollaa ele + + + Inconsistent with the last drawing, please redraw + Ei ole sama edellisen kanssa, piirrä uudelleen + + + Device is locked, unlocked after %1 minutes + Tietokone on lukittu, avataan %1 minuutin kuluttua + + + Modify gesture password + Muokkaa elettä + + + Please draw the current gesture password + Piirrä nykyinen ele + + + Modified successfully + Muutettu onnistuneesti + + + Drawing error, Contact the administrator to reset + Piirtovirhe, ota yhteyttä järjestelmänvalvojaan nollaamista varten. + + + Cancel + Peruuta + + + Ok + OK + + + Drawing error, %1 chances left. Contact the administrator to reset + Piirtovirhe, %1 yritystä jäljellä. Ota yhteyttä järjestelmänvalvojaan nollaamista varten. + + + Setup completed Start unlock + Asennus valmis, aloita lukituksen avaaminen + + + Unlock with gesture password + Avaa lukitus eleellä + + + Minimum 4 points, please redraw + Vähintään 4 pistettä, piirrä uudelleen + + + Contact the administrator to reset + Ota yhteyttä järjestelmänvalvojaan nollaamista varten + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_fr.ts b/plugins/login-gesture/translations/login-gesture_fr.ts new file mode 100644 index 00000000..6f6b39ff --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_fr.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Mot de passe gestuel activé + + + For first time use, please set the gesture password first + Pour la première utilisation, veuillez d'abord définir le mot de passe gestuel. + + + Set gesture password + Définir un mot de passe gestuel + + + Please draw a gesture password + Veuillez dessiner un mot de passe gestuel. + + + Please draw the gesture password again + Veuillez saisir à nouveau le mot de passe gestuel. + + + Setup completed Start login + Configuration terminée. Lancer la connexion. + + + Forgot gesture password + Mot de passe gestuel oublié + + + Sign in with gesture password + Se connecter avec un mot de passe gestuel + + + Gesture password has been reset + Mot de passe gestuel réinitialisé + + + Please reset the gesture password + Veuillez réinitialiser le mot de passe gestuel. + + + Inconsistent with the last drawing, please redraw + Incompatible avec le dernier dessin, veuillez redessiner. + + + Device is locked, unlocked after %1 minutes + L'appareil est verrouillé, déverrouillé après %1 minutes + + + Modify gesture password + Modifier le mot de passe gestuel + + + Please draw the current gesture password + Veuillez dessiner le mot de passe gestuel actuel. + + + Modified successfully + Modifié avec succès + + + Drawing error, Contact the administrator to reset + Erreur de dessin, contactez l'administrateur pour réinitialiser + + + Cancel + Annuler + + + Ok + Ok + + + Drawing error, %1 chances left. Contact the administrator to reset + Erreur de dessin, %1 chances restantes. Contactez l'administrateur pour réinitialiser. + + + Setup completed Start unlock + Configuration terminée Démarrer le déverrouillage + + + Unlock with gesture password + Déverrouiller avec un mot de passe gestuel + + + Minimum 4 points, please redraw + Minimum 4 points, veuillez redessiner + + + Contact the administrator to reset + Contactez l'administrateur pour réinitialiser + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_hu.ts b/plugins/login-gesture/translations/login-gesture_hu.ts new file mode 100644 index 00000000..196c21ff --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_hu.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Kézmozdulat jelszó engedélyezve + + + For first time use, please set the gesture password first + Az első használat előtt, kérjük állítsa be a kézmozdulat jelszót + + + Set gesture password + Kézmozdulat jelszó beállítása + + + Please draw a gesture password + Kérjük rajzoljon egy kézmozdulat jelszót + + + Please draw the gesture password again + Kérjük rajzoljon egy kézmozdulat jelszót újra + + + Setup completed Start login + A beállítás sikeres, A bejelentkezés megkezdése + + + Forgot gesture password + Elfelejtett kézmozdulat jelszó + + + Sign in with gesture password + Jelentkezzen be kézmozdulat jelszóval + + + Gesture password has been reset + A kézmozdulat jelszó frissítve + + + Please reset the gesture password + Kérjük frissítse a kézmozdulat jelszót + + + Inconsistent with the last drawing, please redraw + Nem egyezik az előző rajzzal, kérjük rajzolja újra + + + Device is locked, unlocked after %1 minutes + + + + Modify gesture password + Kézmozdulat jelszó módosítása + + + Please draw the current gesture password + Kérjük adja meg a jelenlegi kézmozdulat jelszót + + + Modified successfully + A módosítás sikeres + + + Drawing error, Contact the administrator to reset + + + + Cancel + + + + Ok + + + + Drawing error, %1 chances left. Contact the administrator to reset + + + + Setup completed Start unlock + + + + Unlock with gesture password + + + + Minimum 4 points, please redraw + + + + Contact the administrator to reset + + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_ja.ts b/plugins/login-gesture/translations/login-gesture_ja.ts new file mode 100644 index 00000000..818de43d --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_ja.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + ジェスチャパスワードが有効化されました + + + For first time use, please set the gesture password first + 初めて使用する場合、まずはジェスチャパスワードを設定してください。 + + + Set gesture password + ジェスチャパスワードを設定 + + + Please draw a gesture password + ジェスチャパスワードを描いてください + + + Please draw the gesture password again + もう一度、ジェスチャパスワードを描いてください + + + Setup completed Start login + セットアップが完了しました。ログインを開始してください。 + + + Forgot gesture password + ジェスチャパスワードを忘れました + + + Sign in with gesture password + ジェスチャパスワードでサインイン + + + Gesture password has been reset + ジェスチャパスワードがリセットされました + + + Please reset the gesture password + ジェスチャパスワードをリセットしてください + + + Inconsistent with the last drawing, please redraw + 前回と違います。書き直してください。 + + + Device is locked, unlocked after %1 minutes + + + + Modify gesture password + ジェスチャパスワードを編集 + + + Please draw the current gesture password + 現在のジェスチャパスワードを描いてください + + + Modified successfully + 正常に編集されました + + + Drawing error, Contact the administrator to reset + + + + Cancel + + + + Ok + + + + Drawing error, %1 chances left. Contact the administrator to reset + + + + Setup completed Start unlock + + + + Unlock with gesture password + + + + Minimum 4 points, please redraw + + + + Contact the administrator to reset + + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_nl.ts b/plugins/login-gesture/translations/login-gesture_nl.ts new file mode 100644 index 00000000..426e5e30 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_nl.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Gebarenwachtwoord is ingeschakeld + + + For first time use, please set the gesture password first + Stel eerst een gebarenwachtwoord in + + + Set gesture password + Gebarenwachtwoord instellen + + + Please draw a gesture password + Teken het gewenste gebaar + + + Please draw the gesture password again + Teken het gebaar nogmaals + + + Setup completed Start login + Het instellen is voltooid + + + Forgot gesture password + Gebarenwachtwoord vergeten + + + Sign in with gesture password + Inloggen met gebarenwachtwoord + + + Gesture password has been reset + Het gebarenwachtwoord is hersteld + + + Please reset the gesture password + Herstel het gebarenwachtwoord + + + Inconsistent with the last drawing, please redraw + De gebaren komen niet overeen. + + + Device is locked, unlocked after %1 minutes + Het apparaat wordt over %1 minuten ontgrendeld + + + Modify gesture password + Gebarenwachtwoord aanpassen + + + Please draw the current gesture password + Teken het huidige gebarenwachtwoord + + + Modified successfully + Het wachtwoord is aangepast + + + Drawing error, Contact the administrator to reset + Fout tijdens tekenen - neem contact op met de beheerder + + + Cancel + Annuleren + + + Ok + Oké + + + Drawing error, %1 chances left. Contact the administrator to reset + Fout tijdens tekenen - nog %1 pogingen te gaan; neem anders contact op met de beheerder + + + Setup completed Start unlock + Het instellen is voltooid + + + Unlock with gesture password + Ontgrendelen met gebarenwachtwoord + + + Minimum 4 points, please redraw + Het gebaar dient uit minimaal 4 punten te bestaan + + + Contact the administrator to reset + Neem contact op met de beheerder + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_pl.ts b/plugins/login-gesture/translations/login-gesture_pl.ts new file mode 100644 index 00000000..0c8c5152 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_pl.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Hasło wzór jest włączone + + + For first time use, please set the gesture password first + Przy pierwszym użyciu najpierw ustaw wzór hasła + + + Set gesture password + Ustaw wzór hasła + + + Please draw a gesture password + Narysuj wzór hasła + + + Please draw the gesture password again + Narysuj ponownie wzór hasła + + + Setup completed Start login + Konfiguracja zakończona, przejdź do logowania + + + Forgot gesture password + Zapomnij wzór hasła + + + Sign in with gesture password + Zaloguj za pomocą wzoru hasła + + + Gesture password has been reset + Wzór hasła został zresetowany + + + Please reset the gesture password + Zresetuj wzór hasła + + + Inconsistent with the last drawing, please redraw + Rozbieżność z poprzednim rysunkiem, narysuj ponownie. + + + Device is locked, unlocked after %1 minutes + Urządzenie zablokowane, odblokowanie za %1 minut + + + Modify gesture password + Zmodyfikuj hasło wzór + + + Please draw the current gesture password + Narysuj aktualny wzór hasła + + + Modified successfully + Zmodyfikowano pomyślnie + + + Drawing error, Contact the administrator to reset + Błąd rysowania, skontaktuj się z administratorem, aby zresetować hasło + + + Cancel + Anuluj + + + Ok + Ok + + + Drawing error, %1 chances left. Contact the administrator to reset + Błąd rysowania, pozostały %1 próby. Skontaktuj się z administratorem, aby zresetować hasło + + + Setup completed Start unlock + Konfiguracja zakończona, przejdź do logowania + + + Unlock with gesture password + Odblokuj za pomocą wzoru hasła + + + Minimum 4 points, please redraw + Co najmniej 4 punkty, narysuj ponownie. + + + Contact the administrator to reset + Skontaktuj się z administratorem, aby zresetować hasło + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_pt.ts b/plugins/login-gesture/translations/login-gesture_pt.ts new file mode 100644 index 00000000..ff713f90 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_pt.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + A palavra-passe gestual está ativada + + + For first time use, please set the gesture password first + Para primeira utilização, por favor defina a palavra-passe gestual primeiro + + + Set gesture password + Definir palavra-passe gestual + + + Please draw a gesture password + Por favor desenhe uma palavra-passe gestual + + + Please draw the gesture password again + Por favor desenhe novamente a palavra-passe gestual + + + Setup completed Start login + Instalação completa. Iniciar sessão + + + Forgot gesture password + Esquecer palavra-passe gestual + + + Sign in with gesture password + Iniciar sessão com palavra-passe gestual + + + Gesture password has been reset + A palavra-passe gestual foi reposta + + + Please reset the gesture password + Por favor reponha a palavra-passe gestual + + + Inconsistent with the last drawing, please redraw + Inconsistência com o último desenho, por favor redesenhe + + + Device is locked, unlocked after %1 minutes + O dispositivo está trancado, desbloqueado após %1 minutos + + + Modify gesture password + Modificar a palavra-passe gestual + + + Please draw the current gesture password + Por favor desenhe a palavra-passe gestual atual + + + Modified successfully + Modificado com sucesso + + + Drawing error, Contact the administrator to reset + Erro de desenho. Contacte o administrador para repor + + + Cancel + Cancelar + + + Ok + Ok + + + Drawing error, %1 chances left. Contact the administrator to reset + Erro de desenho, restam %1 oportunidades. Contacte o administrador para repor + + + Setup completed Start unlock + Instalação completa. Iniciar desbloqueio + + + Unlock with gesture password + Destrancar com palavra-passe gestual + + + Minimum 4 points, please redraw + Mínimo 4 pontos, por favor redesenhe + + + Contact the administrator to reset + Contacte o administrador para repor + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_pt_BR.ts b/plugins/login-gesture/translations/login-gesture_pt_BR.ts new file mode 100644 index 00000000..b3cb6c9d --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_pt_BR.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + A senha por gestos está ativada + + + For first time use, please set the gesture password first + No primeiro uso, crie a senha por gestos + + + Set gesture password + Criar senha por gestos + + + Please draw a gesture password + Desenhe a senha por gestos + + + Please draw the gesture password again + Desenhe a senha por gestos novamente + + + Setup completed Start login + Configuração concluída. Entrar + + + Forgot gesture password + Esqueci a senha por gestos + + + Sign in with gesture password + Entrar com a senha por gestos + + + Gesture password has been reset + A senha por gestos foi redefinida + + + Please reset the gesture password + Redefinir senha por gestos + + + Inconsistent with the last drawing, please redraw + O desenho não confere com o anterior, tente novamente + + + Device is locked, unlocked after %1 minutes + O dispositivo está bloqueado, aguarde %1 minutos + + + Modify gesture password + Alterar senha por gestos + + + Please draw the current gesture password + Desenhe a senha por gestos atual + + + Modified successfully + Alteração bem-sucedida + + + Drawing error, Contact the administrator to reset + Desenho incorreto. Contate o administrador para redefinir + + + Cancel + Cancelar + + + Ok + OK + + + Drawing error, %1 chances left. Contact the administrator to reset + Desenho incorreto. Restam %1 tentativas. Contate o administrador para redefinir + + + Setup completed Start unlock + Configuração concluída. Desbloquear + + + Unlock with gesture password + Desbloquear com a senha por gestos + + + Minimum 4 points, please redraw + Mínimo de 4 pontos. Desenhe novamente + + + Contact the administrator to reset + Contate o administrador para redefinir + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_ru.ts b/plugins/login-gesture/translations/login-gesture_ru.ts new file mode 100644 index 00000000..101c663d --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_ru.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Графический пароль активирован + + + For first time use, please set the gesture password first + При первом использовании, пожалуйста, сначала установите графический пароль + + + Set gesture password + Установка графического пароля + + + Please draw a gesture password + Пожалуйста, нарисуйте графический пароль + + + Please draw the gesture password again + Пожалуйста, нарисуйте графический пароль снова + + + Setup completed Start login + Настройка завершена. Можно войти + + + Forgot gesture password + Забыли графический пароль + + + Sign in with gesture password + Вход в систему с графическим паролем + + + Gesture password has been reset + Графический пароль был сброшен + + + Please reset the gesture password + Пожалуйста, сбросьте графический пароль + + + Inconsistent with the last drawing, please redraw + Не соответствует последнему рисунку, повторите пожалуйста + + + Device is locked, unlocked after %1 minutes + + + + Modify gesture password + Изменить графический пароль + + + Please draw the current gesture password + Пожалуйста, нарисуйте текущий графический пароль + + + Modified successfully + Изменено успешно + + + Drawing error, Contact the administrator to reset + + + + Cancel + + + + Ok + + + + Drawing error, %1 chances left. Contact the administrator to reset + + + + Setup completed Start unlock + + + + Unlock with gesture password + + + + Minimum 4 points, please redraw + + + + Contact the administrator to reset + + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_sq.ts b/plugins/login-gesture/translations/login-gesture_sq.ts new file mode 100644 index 00000000..22e76f8f --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_sq.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Është aktivizuar fjalëkalim me gjeste + + + For first time use, please set the gesture password first + Për herë të parë përdorimi, ju lutemi, së pari caktoni fjalëkalim me gjeste + + + Set gesture password + Caktoni fjalëkalim me gjeste + + + Please draw a gesture password + Ju lutemi, vizatoni një fjalëkalim me gjeste + + + Please draw the gesture password again + Ju lutemi, vizatoni sërish fjalëkalimin me gjeste + + + Setup completed Start login + Ujdisje e plotësuar. Nisni hyrjen + + + Forgot gesture password + U harrua fjalëkalim me gjeste + + + Sign in with gesture password + Bëni hyrjen me fjalëkalim me gjeste + + + Gesture password has been reset + Fjalëkalimi me gjeste u ricaktua + + + Please reset the gesture password + Ju lutemi, ricaktoni fjalëkalimin me gjeste + + + Inconsistent with the last drawing, please redraw + S’përputhet me vizatimin e fundit, ju lutemi, rivizatojeni + + + Device is locked, unlocked after %1 minutes + Pajisja është e kyçur, shkyçet pas %1 minutash + + + Modify gesture password + Ndryshoni fjalëkalim me gjeste + + + Please draw the current gesture password + Ju lutemi, vizatoni fjalëkalimin e tanishëm me gjeste + + + Modified successfully + U ndryshua me sukses + + + Drawing error, Contact the administrator to reset + Gabim vizatimi, lidhuni me përgjegjësin për ta ricakuar + + + Cancel + Anuloje + + + Ok + OK + + + Drawing error, %1 chances left. Contact the administrator to reset + Gabim vizatimi, edhe %1 prova. Lidhuni me përgjegjësin për ta ricakuar + + + Setup completed Start unlock + Ujdisja u plotësua. Nisni shkyçjen + + + Unlock with gesture password + Shkyçe me fjalëkalim me gjeste + + + Minimum 4 points, please redraw + Minimumi 4 pika, ju lutemi, rivizatojeni + + + Contact the administrator to reset + Lidhuni me përgjegjësin për ta ricaktuar + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_tr.ts b/plugins/login-gesture/translations/login-gesture_tr.ts new file mode 100644 index 00000000..7931aa6e --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_tr.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Hareket parolası etkinleştirildi + + + For first time use, please set the gesture password first + İlk kullanım için, lütfen önce hareket parolasını ayarlayın + + + Set gesture password + Hareket parolasını ayarlayın + + + Please draw a gesture password + Lütfen bir hareket parolası çizin + + + Please draw the gesture password again + Lütfen hareket parolasını tekrar çizin + + + Setup completed Start login + Kurulum tamamlandı Oturum açmayı başlat + + + Forgot gesture password + Hareket parolamı unuttum + + + Sign in with gesture password + Hareket parolasıyla oturum açın + + + Gesture password has been reset + Hareket parolası sıfırlandı + + + Please reset the gesture password + Lütfen hareket parolasını sıfırlayın + + + Inconsistent with the last drawing, please redraw + Son çizimle tutarsız, lütfen yeniden çizin + + + Device is locked, unlocked after %1 minutes + Cihaz kilitli, %1 dakika sonra kilidi açılıyor + + + Modify gesture password + Hareket parolasını değiştir + + + Please draw the current gesture password + Lütfen mevcut hareket parolasını çizin + + + Modified successfully + Başarıyla değiştirildi + + + Drawing error, Contact the administrator to reset + Çizim hatası, sıfırlamak için yöneticiyle iletişime geçin + + + Cancel + Vazgeç + + + Ok + Tamam + + + Drawing error, %1 chances left. Contact the administrator to reset + Çizim hatası, %1 deneme kaldı. Sıfırlamak için yöneticiyle iletişime geçin + + + Setup completed Start unlock + Kurulum tamamlandı. Kilidi açmaya başla + + + Unlock with gesture password + Hareket şifresiyle kilidi açın + + + Minimum 4 points, please redraw + En az 4 nokta, lütfen yeniden çizin + + + Contact the administrator to reset + Sıfırlamak için yöneticiyle iletişime geçin + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_uk.ts b/plugins/login-gesture/translations/login-gesture_uk.ts new file mode 100644 index 00000000..9a4651c6 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_uk.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + Увімкнено жестовий пароль + + + For first time use, please set the gesture password first + Для першого використання, будь ласка, спочатку встановіть жестовий пароль + + + Set gesture password + Встановити жестовий пароль + + + Please draw a gesture password + Будь ласка, намалюйте жестовий пароль + + + Please draw the gesture password again + Будь ласка, намалюйте жестовий пароль ще раз + + + Setup completed Start login + Налаштувати завершений початковий вхід + + + Forgot gesture password + Не пам'ятаю жестовий пароль + + + Sign in with gesture password + Увійти за допомогою жестового пароля + + + Gesture password has been reset + Жестовий пароль скинуто + + + Please reset the gesture password + Будь ласка, скиньте жестовий пароль + + + Inconsistent with the last drawing, please redraw + Не збігається із останнім малюнком, будь ласка, повторіть + + + Device is locked, unlocked after %1 minutes + Пристрій заблоковано. Його розблокування відбудеться за %1 хвилин + + + Modify gesture password + Змінити жестовий пароль + + + Please draw the current gesture password + Будь ласка, намалюйте поточний жестовий пароль + + + Modified successfully + Успішно змінено + + + Drawing error, Contact the administrator to reset + Помилка малювання. Для скидання зверніться до адміністратора + + + Cancel + Скасувати + + + Ok + Гаразд + + + Drawing error, %1 chances left. Contact the administrator to reset + Помилка малювання. Лишилося %1 спроб. Для скидання зверніться до адміністратора + + + Setup completed Start unlock + Налаштування завершено. Можна починати + + + Unlock with gesture password + Розблокувати за допомогою жесту + + + Minimum 4 points, please redraw + Мінімум 4 точки, будь ласка, повторіть малювання + + + Contact the administrator to reset + Для скидання зверніться до адміністратора + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_zh_CN.ts b/plugins/login-gesture/translations/login-gesture_zh_CN.ts new file mode 100644 index 00000000..15fa12c6 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_zh_CN.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + 手势密码已开启 + + + For first time use, please set the gesture password first + 首次使用,请先设置手势密码 + + + Set gesture password + 设置手势密码 + + + Please draw a gesture password + 请绘制手势密码 + + + Please draw the gesture password again + 请再次绘制手势密码 + + + Setup completed Start login + 设置完成 开始登录 + + + Forgot gesture password + 忘记手势密码 + + + Sign in with gesture password + 使用手势密码登录 + + + Gesture password has been reset + 手势密码已重置 + + + Please reset the gesture password + 请重新设置手势密码 + + + Inconsistent with the last drawing, please redraw + 与上次绘制不一致,请重新绘制 + + + Device is locked, unlocked after %1 minutes + 设备已锁定,%1分钟后解锁 + + + Modify gesture password + 修改手势密码 + + + Please draw the current gesture password + 请绘制当前手势密码 + + + Modified successfully + 修改成功 + + + Drawing error, Contact the administrator to reset + 绘制错误,可联系管理员重置 + + + Cancel + 取消 + + + Ok + 确定 + + + Drawing error, %1 chances left. Contact the administrator to reset + 绘制错误,剩余%1次机会。可联系管理员重置 + + + Setup completed Start unlock + 设置完成开始解锁 + + + Unlock with gesture password + 使用手势密码解锁 + + + Minimum 4 points, please redraw + 最少连接4个点,请重新绘制 + + + Contact the administrator to reset + 可联系管理员重置手势密码 + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_zh_HK.ts b/plugins/login-gesture/translations/login-gesture_zh_HK.ts new file mode 100644 index 00000000..2f31138e --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_zh_HK.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + 手勢密碼已開啟 + + + For first time use, please set the gesture password first + 首次使用,請先設定手勢密碼 + + + Set gesture password + 設定手勢密碼 + + + Please draw a gesture password + 請繪製手勢密碼 + + + Please draw the gesture password again + 請再次繪製手勢密碼 + + + Setup completed Start login + 設定完成開始登入 + + + Forgot gesture password + 忘記手勢密碼 + + + Sign in with gesture password + 使用手勢密碼登入 + + + Gesture password has been reset + 手勢密碼已重置 + + + Please reset the gesture password + 請重新設定手勢密碼 + + + Inconsistent with the last drawing, please redraw + 與上次繪製不一致,請重新繪製 + + + Device is locked, unlocked after %1 minutes + 設備已鎖定,%1分鐘後解鎖 + + + Modify gesture password + 修改手勢密碼 + + + Please draw the current gesture password + 請繪製當前手勢密碼 + + + Modified successfully + 修改成功 + + + Drawing error, Contact the administrator to reset + 繪製錯誤,可聯系管理員重置 + + + Cancel + 取消 + + + Ok + 確定 + + + Drawing error, %1 chances left. Contact the administrator to reset + 繪製錯誤,剩餘%1次機會。可聯絡管理員重置 + + + Setup completed Start unlock + 設定完成開始解鎖 + + + Unlock with gesture password + 使用手勢密碼解鎖 + + + Minimum 4 points, please redraw + 最少連接4個點,請重新繪製 + + + Contact the administrator to reset + 可聯絡管理員重置手勢密碼 + + + \ No newline at end of file diff --git a/plugins/login-gesture/translations/login-gesture_zh_TW.ts b/plugins/login-gesture/translations/login-gesture_zh_TW.ts new file mode 100644 index 00000000..8b5ebfc3 --- /dev/null +++ b/plugins/login-gesture/translations/login-gesture_zh_TW.ts @@ -0,0 +1,97 @@ + + + gestureLogin::TranslastionDoc + + Gesture password is enabled + 手勢密碼已開啟 + + + For first time use, please set the gesture password first + 首次使用,請先設定手勢密碼 + + + Set gesture password + 設定手勢密碼 + + + Please draw a gesture password + 請繪製手勢密碼 + + + Please draw the gesture password again + 請再次繪製手勢密碼 + + + Setup completed Start login + 設定完成開始登入 + + + Forgot gesture password + 忘記手勢密碼 + + + Sign in with gesture password + 使用手勢密碼登入 + + + Gesture password has been reset + 手勢密碼已重置 + + + Please reset the gesture password + 請重新設定手勢密碼 + + + Inconsistent with the last drawing, please redraw + 與上次繪製不一致,請重新繪製 + + + Device is locked, unlocked after %1 minutes + 設備已鎖定,%1分鐘後解鎖 + + + Modify gesture password + 修改手勢密碼 + + + Please draw the current gesture password + 請繪製當前手勢密碼 + + + Modified successfully + 修改成功 + + + Drawing error, Contact the administrator to reset + 繪製錯誤,可聯系管理員重置 + + + Cancel + 取消 + + + Ok + 確定 + + + Drawing error, %1 chances left. Contact the administrator to reset + 繪製錯誤,剩餘%1次機會。可聯絡管理員重設 + + + Setup completed Start unlock + 設定完成開始解鎖 + + + Unlock with gesture password + 使用手勢密碼解鎖 + + + Minimum 4 points, please redraw + 最少連接4個點,請重新繪製 + + + Contact the administrator to reset + 可聯絡管理員重設手勢密碼 + + + \ No newline at end of file diff --git a/plugins/login-gesture/utils/tokenCrypt.h b/plugins/login-gesture/utils/tokenCrypt.h new file mode 100644 index 00000000..7c8f2ad1 --- /dev/null +++ b/plugins/login-gesture/utils/tokenCrypt.h @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2011 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef TOKENCRYPT_H +#define TOKENCRYPT_H + +#include +#include + +#include +#include + +namespace gestureEncrypt { +/** + * @brief crypt函数是否支持SM3算法 + * crypt使用固定的key和salt进行加密,把加密结果与已知的正确结果进行比对,相等则支持,反之不支持 + * @return true 支持 + * @return false 不支持 + */ +inline bool supportSM3() +{ + char password[] = "Hello world!"; + char salt[] = "$8$saltstring"; + const QString cryptResult = "$8$saltstring$6RCuSuWbADZmLALkvsvtcYYzhrw3xxpuDcqwdPIWxTD"; + return crypt(password, salt) == cryptResult; +} + +inline const QByteArray getCryptSalt(const QByteArray &key) +{ + QByteArray retsult = ""; + int count = 0; + for (const auto value : key) { + if (value == '$') { + retsult += value; + count++; + if (count == 3) { + return retsult; + } + } else { + if (count > 0) { + retsult += value; + } + } + } + + return retsult; +} + +inline QString cryptUserPassword(const QString &password, const QByteArray &salt) +{ + return crypt(password.toUtf8().data(), salt); +} + +inline QString getSalt() +{ + /* + NOTE(kirigaya): Password is a combination of salt and crypt function. + slat is begin with $6$, 16 byte of random values, at the end of $. + crypt function will return encrypted values. + */ + const QString seedChars("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); + char salt[] = "$6$................$"; + if (supportSM3()) { + salt[1] = '8'; + } + + std::random_device r; + std::default_random_engine e1(r()); + std::uniform_int_distribution uniform_dist(0, seedChars.size() - 1); // seedChars.size()是64,生成随机数的范围应该写成[0, 63]。 + + // Random access to a character in a restricted list + for (int i = 0; i != 16; i++) { + salt[3 + i] = seedChars.at(uniform_dist(e1)).toLatin1(); + } + + return salt; +} + +inline QString cryptUserPassword(const QString &password) +{ + return crypt(password.toUtf8().data(), getSalt().toLatin1()); +} +}; // namespace gestureEncrypt +#endif diff --git a/plugins/login-gesture/utils/translastiondoc.cpp b/plugins/login-gesture/utils/translastiondoc.cpp new file mode 100644 index 00000000..06c473d8 --- /dev/null +++ b/plugins/login-gesture/utils/translastiondoc.cpp @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "translastiondoc.h" +#include "waypointmodel.h" + +#include +#include +#include +#include +#include + +const QString kTransFile = "%1/login-gesture_%2.qm"; + +using namespace gestureLogin; + +TranslastionDoc::TranslastionDoc(QObject *parent) + : QObject(parent) + , m_translator(new QTranslator(this)) +{ + setLocale(WayPointModel::instance()->localeName()); + connect(WayPointModel::instance(), &WayPointModel::localeChanged, this, &TranslastionDoc::setLocale); +} + +TranslastionDoc *TranslastionDoc::instance() +{ + static TranslastionDoc doc; + return &doc; +} + +QString TranslastionDoc::getDoc(DocIndex index) +{ + return m_doc.value(index, ""); +} + +void TranslastionDoc::setLocale(const QString &localName) +{ + auto name = localName; + if (name.isEmpty()) { + name = QLocale::system().name(); + } + + qApp->removeTranslator(m_translator); + QString transFile = kTransFile.arg(QM_FILES_DIR).arg(name); + if (QFile(transFile).exists()) { + m_translator->load(transFile); + qApp->installTranslator(m_translator); + initDoc(); + } else { + qWarning() << transFile << "not exists"; + } +} + +void TranslastionDoc::initDoc() +{ + m_doc.clear(); + m_doc[DocIndex::Enabled] = tr("Gesture password is enabled"); + m_doc[DocIndex::RequestFirstEnroll] = tr("For first time use, please set the gesture password first"); + m_doc[DocIndex::SetPasswd] = tr("Set gesture password"); + m_doc[DocIndex::RequestDrawing] = tr("Please draw a gesture password"); + m_doc[DocIndex::RequestDrawingAgain] = tr("Please draw the gesture password again"); + m_doc[DocIndex::ForgotPasswd] = tr("Forgot gesture password"); + m_doc[DocIndex::PasswdCleared] = tr("Gesture password has been reset"); + m_doc[DocIndex::NeedResetPasswd] = tr("Please reset the gesture password"); + m_doc[DocIndex::PathError] = tr("Minimum 4 points, please redraw"); + m_doc[DocIndex::Inconsistent] = tr("Inconsistent with the last drawing, please redraw"); + m_doc[DocIndex::ContactAdmin] = tr("Drawing error, Contact the administrator to reset"); + m_doc[DocIndex::DeviceLock] = tr("Device is locked, unlocked after %1 minutes"); + m_doc[DocIndex::ModifyPasswd] = tr("Modify gesture password"); + m_doc[DocIndex::DrawCurrentPasswd] = tr("Please draw the current gesture password"); + m_doc[DocIndex::EnrollDone] = tr("Modified successfully"); + m_doc[DocIndex::Cancel] = tr("Cancel"); + m_doc[DocIndex::Ok] = tr("Ok"); + m_doc[DocIndex::AuthErrorWithTimes] = tr("Drawing error, %1 chances left. Contact the administrator to reset"); + m_doc[DocIndex::DeviceLockHelp] = tr("Contact the administrator to reset"); + + // 登录器与锁屏的差异部分 + if (WayPointModel::instance()->isLockApp()) { + m_doc[DocIndex::LoginAfterEnroll] = tr("Setup completed Start unlock"); + m_doc[DocIndex::LoginStart] = tr("Unlock with gesture password"); + } else { + m_doc[DocIndex::LoginAfterEnroll] = tr("Setup completed Start login"); + m_doc[DocIndex::LoginStart] = tr("Sign in with gesture password"); + } +} diff --git a/plugins/login-gesture/utils/translastiondoc.h b/plugins/login-gesture/utils/translastiondoc.h new file mode 100644 index 00000000..85d76a5d --- /dev/null +++ b/plugins/login-gesture/utils/translastiondoc.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef TRANSLASTIONDOC_H +#define TRANSLASTIONDOC_H + +#include +#include + +class QTranslator; + +namespace gestureLogin { + +enum class DocIndex { + Enabled, + RequestFirstEnroll, + SetPasswd, + RequestDrawing, + RequestDrawingAgain, + LoginAfterEnroll, + ForgotPasswd, + LoginStart, + GestureLockStart, + PasswdCleared, + NeedResetPasswd, + PathError, + Inconsistent, + GestureAuthError, + ContactAdmin, + DeviceLock, + ModifyPasswd, + DrawCurrentPasswd, + EnrollDone, + Cancel, + Ok, + AuthErrorWithTimes, + DeviceLockHelp +}; + +// 在这里加载翻译文件,提供翻译内容 +class TranslastionDoc : public QObject +{ + Q_OBJECT + +public: + static TranslastionDoc *instance(); + QString getDoc(DocIndex); + +public Q_SLOTS: + void setLocale(const QString &); + +private: + explicit TranslastionDoc(QObject *parent = nullptr); + void initDoc(); + +private: + QMap m_doc; + QTranslator *m_translator; +}; +} // namespace gestureLogin +#endif // TRANSLASTIONDOC_H diff --git a/plugins/login-gesture/utils/userservice.cpp b/plugins/login-gesture/utils/userservice.cpp new file mode 100644 index 00000000..8bb3ac50 --- /dev/null +++ b/plugins/login-gesture/utils/userservice.cpp @@ -0,0 +1,137 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "userservice.h" +#include "waypointmodel.h" + +#include +#include + +const QString kAccountService = "com.deepin.daemon.Accounts"; +const QString kAccountPath = "/com/deepin/daemon/Accounts"; +const QString kUserInterface = "com.deepin.daemon.Accounts.User"; +const QString kPropertyInterface = "org.freedesktop.DBus.Properties"; +const QString kEnableFlag = "PatternEnabled"; +const QString kStateFlag = "PatternState"; + +using namespace gestureLogin; + +UserService::UserService(const QString &name, QObject *parent) + : QObject(parent) + , m_userInter(nullptr) + , m_currentName(name) +{ + init(); +} + +UserService *UserService::instance() +{ + static UserService s(""); + return &s; +} + +void UserService::setUserName(const QString &userName) +{ + // 不论设置用户名多少,都重新做初始化 + m_currentName = userName; + init(); +} + +bool UserService::gestureEnabled() +{ + auto rst = false; + if (m_userInter && m_userInter->isValid()) { + rst = m_userInter->property("PatternEnabled").toBool(); + } + + return rst; +} + +int UserService::gestureFlags() +{ + auto rst = -1; + if (m_userInter && m_userInter->isValid()) { + rst = m_userInter->property("PatternState").toInt(); + } + + return rst; +} + +QString UserService::localeName() +{ + QString rst = ""; + if (m_userInter && m_userInter->isValid()) { + rst = m_userInter->property("Locale").toString(); + } + + return rst; +} + +void UserService::enroll(const QString &data) +{ + if (data.isEmpty()) { + qDebug() << Q_FUNC_INFO << "enroll data empty"; + return; + } + + if (m_userInter && m_userInter->isValid()) { + m_userInter->call("SetPattern", data); + qDebug() << Q_FUNC_INFO << "enrolled" << m_userInter->path(); + } +} + +void UserService::onPropertiesChanged(const QDBusMessage& msg) +{ + QList arguments = msg.arguments(); + if (3 != arguments.count()) + return; + + QString interfaceName = msg.arguments().at(0).toString(); + + if (interfaceName != kUserInterface) + return; + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + QStringList keys = changedProps.keys(); + if (changedProps.keys().contains(kStateFlag)) { + WayPointModel::instance()->setGestureState(changedProps.value(kStateFlag).toInt()); + } +} + +void UserService::init() +{ + if (m_userInter) { + m_userInter->disconnect(); + delete m_userInter; + m_userInter = nullptr; + } + + if (!m_userInterpath.isEmpty()) { + QDBusConnection::systemBus().disconnect(kAccountService, m_userInterpath, kPropertyInterface, "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertiesChanged(QDBusMessage))); + } + + static QDBusInterface accountInter(kAccountService, kAccountPath, kAccountService, QDBusConnection::systemBus(), this); + QDBusReply reply = accountInter.call("FindUserByName", m_currentName); + if (reply.isValid()) { + m_userInterpath = reply; + } + + if (m_userInterpath.isEmpty()) { + return; + } + + m_userInter = new QDBusInterface(kAccountService, m_userInterpath, kUserInterface, QDBusConnection::systemBus(), this); + if (m_userInter->isValid()) { + bool connected = QDBusConnection::systemBus().connect(kAccountService, m_userInterpath, kPropertyInterface, "PropertiesChanged", "sa{sv}as", this, SLOT(onPropertiesChanged(QDBusMessage))); + qDebug() << Q_FUNC_INFO << "property change handle" << connected; + + auto model = WayPointModel::instance(); + model->setGestureEnabled(gestureEnabled()); + model->setGestureState(gestureFlags()); + model->setLocaleName(localeName()); + } else { + qWarning() << Q_FUNC_INFO << "user interface invalid" << m_userInterpath; + } + +} diff --git a/plugins/login-gesture/utils/userservice.h b/plugins/login-gesture/utils/userservice.h new file mode 100644 index 00000000..2e25f30f --- /dev/null +++ b/plugins/login-gesture/utils/userservice.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DBUSSERVICE_H +#define DBUSSERVICE_H + +#include +#include + +namespace gestureLogin { + +// 提供da状态查询与监控 +class UserService : public QObject +{ + Q_OBJECT +public: + static UserService *instance(); + + void setUserName(const QString &); + inline bool isServiceValid() { return m_userInter != nullptr; } + // 查询当前用户手势是否开启 + bool gestureEnabled(); + // 查询当前用户手势状态标识 + int gestureFlags(); + QString localeName(); + + void enroll(const QString &); + +public Q_SLOTS: + void onPropertiesChanged(const QDBusMessage& msg); + +Q_SIGNALS: + void userPatternStateChanged(int); + +private: + explicit UserService(const QString &, QObject *parent = nullptr); + void init(); + +private: + QDBusInterface *m_userInter; + QString m_currentName; + QString m_userInterpath; +}; +} // namespace gestureLogin + +#endif // DBUSSERVICE_H diff --git a/plugins/one-key-login/CMakeLists.txt b/plugins/one-key-login/CMakeLists.txt new file mode 100644 index 00000000..0c64477e --- /dev/null +++ b/plugins/one-key-login/CMakeLists.txt @@ -0,0 +1,15 @@ +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) + +link_libraries( + ${Qt_LIBS} + Dtk${DTK_VERSION_MAJOR}::Core + Dtk${DTK_VERSION_MAJOR}::Widget +) + +set(LIB_NAME one-key-login) + +aux_source_directory(. SRCS) + +add_library(${LIB_NAME} SHARED ${SRCS}) + +install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules) diff --git a/plugins/one-key-login/login.json b/plugins/one-key-login/login.json new file mode 100644 index 00000000..95156e4b --- /dev/null +++ b/plugins/one-key-login/login.json @@ -0,0 +1,4 @@ +{ + "api": "2.0.0", + "pluginType": "Login" +} diff --git a/plugins/one-key-login/login_module.cpp b/plugins/one-key-login/login_module.cpp new file mode 100644 index 00000000..daf5a078 --- /dev/null +++ b/plugins/one-key-login/login_module.cpp @@ -0,0 +1,554 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login_module.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dbusconstant.h" + +DCORE_USE_NAMESPACE + +namespace dss { +namespace module_v2 { + +LoginModule::LoginModule(QObject *parent) + : QObject(parent) + , m_appData(nullptr) + , m_authCallback(nullptr) + , m_messageCallback(nullptr) + , m_loginWidget(nullptr) + , m_appType(AppType::TypeNone) + , m_loadPluginType(Notload) + , m_isAcceptFingerprintSignal(false) + , m_waitAcceptSignalTimer(nullptr) + , m_dconfig(nullptr) + , m_spinner(nullptr) + , m_acceptSleepSignal(false) + , m_authStatus(AuthStatus::None) + , m_needSendAuthType(false) + , m_isLocked(false) + , m_login1SessionSelf(nullptr) + , m_IdentifyWithMultipleUserStarted(false) + , m_loginAuthenticated(false) + , m_authFactors(AuthType::AT_None) +{ + setObjectName(QStringLiteral("LoginModule")); + + const bool isLock = qApp->applicationName().toLower().contains("lock"); + m_appType = isLock ? AppType::Lock : AppType::Login; + qDebug() << "Is lock application: " << isLock << ", application name: "<< qApp->applicationName(); + const QString &dconfigFile = isLock ? "org.deepin.dde.lock" : "org.deepin.dde.lightdm-deepin-greeter"; + m_dconfig = DConfig::create(dconfigFile, dconfigFile, QString(), this); + //华为机型,从override配置中获取是否加载插件 + if (m_dconfig) { + bool showPlugin = m_dconfig->value("enableOneKeylogin", false).toBool(); + m_loadPluginType = showPlugin ? Load : Notload; + if (!showPlugin) + return; + + //OPTIMIZE 不应该和这两个配置耦合,更不应该把开启一键登录的逻辑放到构造函数中! + const auto &designatedLoginPlugin = m_dconfig->value("designatedLoginPlugin", "").toString(); + const auto &defaultLoginPlugin = m_dconfig->value("defaultLoginPlugin", "").toString(); + bool useMe = false; + if (designatedLoginPlugin.isEmpty() && defaultLoginPlugin.isEmpty()) { + useMe = true; + } else if (!designatedLoginPlugin.isEmpty()) { + useMe = designatedLoginPlugin == key(); + } else if (!defaultLoginPlugin.isEmpty()) { + useMe = defaultLoginPlugin == key(); + } + qInfo() << "Load one-key-plugin:" << useMe + << ", designated login plugin:" << designatedLoginPlugin + << ", default login plugin:" << defaultLoginPlugin; + m_loadPluginType = useMe ? Load :Notload; + if (!useMe) + return; + } + + QDBusInterface login1Inter("org.freedesktop.login1", "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + QDBusConnection::systemBus()); + if(login1Inter.isValid()){ + QDBusPendingReply reply = login1Inter.asyncCall("GetSessionByPID" , uint(0)); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, [this, reply, watcher] { + if (!watcher->isError()) { + QString session_self = reply.value().path(); + qDebug() << "Login1 interface call `GetSessionByPID`, reply path: " << session_self; + m_login1SessionSelf = new QDBusInterface("org.freedesktop.login1", session_self, "org.freedesktop.login1.Session", QDBusConnection::systemBus()); + } else { + qWarning() << "Login1 interface error: " << watcher->error().message(); + } + watcher->deleteLater(); + }); + } else { + qWarning() << "Login1 interface is not valid"; + } + + initConnect(); + + // 超时没接收到一键登录信号,视为失败 + m_waitAcceptSignalTimer = new QTimer(this); + m_waitAcceptSignalTimer->setInterval(800); + connect(m_waitAcceptSignalTimer, &QTimer::timeout, this, [this] { + qDebug() << "Start 0.8s, whether accept finger print signal: " << m_isAcceptFingerprintSignal; + stopIdentify(); + m_waitAcceptSignalTimer->stop(); + m_loginAuthenticated = true; + m_IdentifyWithMultipleUserStarted = false; + m_acceptSleepSignal = false; + if (!m_isAcceptFingerprintSignal) { + // 防止刚切换指纹认证stop还没结束。 + QTimer::singleShot(30, this, [this] { + sendAuthTypeToSession(AuthType::AT_All); + }); + } + }, Qt::DirectConnection); + + if (!isLock) { + startCallHuaweiFingerprint(); + } +} + +LoginModule::~LoginModule() +{ + if (m_loginWidget) { + delete m_loginWidget; + } + + if (m_login1SessionSelf) { + delete m_login1SessionSelf; + m_login1SessionSelf = nullptr; + } + + if (m_waitAcceptSignalTimer) { + m_waitAcceptSignalTimer->stop(); + delete m_waitAcceptSignalTimer; + } + + if (m_dconfig) { + delete m_dconfig; + } +} + +void LoginModule::initConnect() +{ + bool isConIsSleep = QDBusConnection::systemBus().connect("org.freedesktop.login1", "/org/freedesktop/login1","org.freedesktop.login1.Manager", + "PrepareForSleep", this, SLOT(slotPrepareForSleep(bool))); + qInfo() << "Whether connect `PrepareForSleep`: " << isConIsSleep; + + + bool isConnectSuccess = QDBusConnection::systemBus().connect(DSS_DBUS::authenticateService, DSS_DBUS::fingerprintAuthPath, DSS_DBUS::fingerprintAuthInterface, + "VerifyStatus", this, SLOT(slotIdentifyStatus(const QString &, const int, const QString &))); + qInfo() << "Whether connect `VerifyStatus`: " << isConnectSuccess; + +} + +void LoginModule::startCallHuaweiFingerprint() +{ + auto failedHandler = [this] { + m_isAcceptFingerprintSignal = false; + // FIXME 此处不能调用回调,因为还没初始化,此处的逻辑应该在setCallBack函数完成后再进行。 + sendAuthTypeToSession(AuthType::AT_All); + }; + + QDBusMessage m = QDBusMessage::createMethodCall(DSS_DBUS::authenticateService, DSS_DBUS::fingerprintAuthPath, DSS_DBUS::fingerprintAuthInterface, + "IdentifyWithMultipleUser"); + // 将消息发送到Dbus + QDBusPendingCall identifyCall = QDBusConnection::systemBus().asyncCall(m); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(identifyCall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, [this, identifyCall, failedHandler, watcher] { + if (!identifyCall.isError()) { + QDBusMessage response = identifyCall.reply(); + //判断Method是否被正确返回 + if (response.type()== QDBusMessage::ReplyMessage) { + m_IdentifyWithMultipleUserStarted = true; + m_waitAcceptSignalTimer->start(); + } else { + failedHandler(); + } + } else { + m_waitAcceptSignalTimer->start(); + } + watcher->deleteLater(); + }); +} + +void LoginModule::init() +{ + initUI(); + updateInfo(); + + if (m_appType == AppType::Lock && !m_acceptSleepSignal) { + //此处延迟0.5s发送,是需要等待dde-session-shell认证方式创建完成 + QTimer::singleShot(500, this, [this] { + sendAuthTypeToSession(AuthType::AT_All); + }); + } +} + +void LoginModule::reset() +{ + init(); +} + +void LoginModule::initUI() +{ + qInfo() << "Login module ui init"; + if (m_loginWidget) { + qWarning() << "Login widget has existed"; + return; + } + m_loginWidget = new QWidget; + m_loginWidget->setAccessibleName(QStringLiteral("LoginWidget")); + m_loginWidget->setMinimumSize(260, 100); + + m_loginWidget->setLayout(new QHBoxLayout); + m_spinner = new DTK_WIDGET_NAMESPACE::DSpinner(m_loginWidget); + m_spinner->setFixedSize(40, 40); + m_loginWidget->layout()->addWidget(m_spinner); + m_spinner->start(); +} + +void LoginModule::updateInfo() +{ + if (!m_messageCallback) { + qWarning() << "Callback message is null"; + return; + } + + // 发送获取属性的请求 + QJsonObject message; + message.insert("CmdType", "GetProperties"); + QJsonArray array; + array.append("AppType"); + array.append("CurrentUser"); + message["Data"] = array; + QJsonDocument doc; + doc.setObject(message); + QString ret = m_messageCallback(doc.toJson(), m_appData); + + // 解析返回值 + QJsonParseError jsonParseError; + const QJsonDocument retDoc = QJsonDocument::fromJson(ret.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || retDoc.isEmpty()) { + qWarning() << "Failed to analysis app type info from shell: " << ret; + return ; + } + + QJsonObject obj = retDoc.object(); + if (obj.value("Code").toInt() != 0) { + qWarning() << "Get properties failed, message: " << obj.value("Message").toString(); + return; + } + + QJsonObject data = obj.value("Data").toObject(); + if (data.contains("AppType")) { + m_appType = (AppType)data.value("AppType").toInt(); + qInfo() << "App type: " << m_appType; + } + + if (data.contains("CurrentUser")) { + QJsonObject user = data.value("CurrentUser").toObject(); + m_userName = user.value("Name").toString(); + qInfo() << "Current user: " << user; + } +} + +void LoginModule::setAppData(AppDataPtr appData) +{ + m_appData = appData; +} + +void LoginModule::setAuthCallback(AuthCallbackFun authCallback) +{ + m_authCallback = authCallback; +} + +void LoginModule::setMessageCallback(MessageCallbackFunc messageCallback) +{ + m_messageCallback = messageCallback; +} + +QString LoginModule::message(const QString &message) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + qWarning() << "Failed to obtain message from shell, message: " << message; + return ""; + } + + QJsonObject retObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + + QJsonObject msgObj = messageDoc.object(); + QString cmdType = msgObj.value("CmdType").toString(); + qInfo() << "Cmd type: " << cmdType; + if (cmdType == "CurrentUserChanged") { + QJsonObject data = msgObj.value("Data").toObject(); + m_userName = data.value("Name").toString(); + qDebug() << "Current user changed, user name: " << m_userName; + } else if (cmdType == "GetConfigs") { + QJsonObject retDataObj; + retDataObj["ShowAvatar"] = false; + retDataObj["ShowUserName"] = false; + retDataObj["ShowSwitchButton"] = false; + retDataObj["ShowLockButton"] = false; + retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::StrongDefault; + retDataObj["AuthType"] = AuthType::AT_Custom; + retDataObj["SupportDefaultUser"] = false; + retDataObj["NotUsedByLoginedUserInGreeter"] = true; + retDataObj["SaveLastAuthType"] = false; + + retObj["Data"] = retDataObj; + } else if (cmdType == "StartAuth"){ + qDebug() << "Start auth, last auth result: " << m_lastAuthResult.result << ", last auth account: " << m_lastAuthResult.account; + QJsonObject data = msgObj.value("Data").toObject(); + m_authStatus = AuthStatus::Start; + int type = data.value("AuthObjectType").toInt(); + if(type == AuthObjectType::LightDM ){ + if (m_isAcceptFingerprintSignal){ + sendAuthData(m_lastAuthResult); + } + if (m_needSendAuthType) { + sendAuthTypeToSession(AuthType::AT_All); + } + } + } else if (cmdType == "AuthState") { + QJsonObject data = msgObj.value("Data").toObject(); + int authType = data.value("AuthType").toInt(); + int authState = data.value("AuthState").toInt(); + // 所有类型验证成功,重置插件状态 + if (authType == AuthType::AT_All && authState == AuthState::AS_Success) { + init(); + } + } else if (cmdType == "LimitsInfo") { + QJsonArray data = msgObj.value("Data").toArray(); + for (const QJsonValue &limitsInfoStr : data) { + const QJsonObject limitsInfoObj = limitsInfoStr.toObject(); + if (limitsInfoObj["flag"].toInt() == AuthType::AT_Password) + m_isLocked = limitsInfoObj["locked"].toBool(); + } + } else if (cmdType == "IsPluginEnabled") { + QJsonObject retDataObj; + + // 满足以下条件启用插件: + // 1. 在登录界面时,一键登录仅在启动或待机休眠唤醒的时候认证一下。 + // 2. 在锁屏界面,休眠或待机唤醒后。 + // 3. 上次A账户验证通过(登录时根据验证结果去跳转对应的用户) + bool enable = (m_appType == AppType::Login && !m_loginAuthenticated) + || (m_appType == AppType::Lock && m_acceptSleepSignal) + || (m_appType == AppType::Login && m_lastAuthResult.result == AuthResult::Success && m_lastAuthResult.account == m_userName); + // 包含指纹认证 + enable = enable && (m_authFactors & AuthType::AT_Fingerprint); + qInfo() << "Enable plugin: " << enable + << ", app type: " << m_appType + << ", authenticated: " << m_loginAuthenticated + << ", accepted sleep signal: " << m_acceptSleepSignal + << ", last auth account: " << m_lastAuthResult.account + << ", current auth account: "<< m_userName + << ", auth factors: " << m_authFactors; + + retDataObj["IsPluginEnabled"] = enable; + retObj["Data"] = retDataObj; + } else if (cmdType == "AuthFactorsChanged") { + QJsonObject data = msgObj.value("Data").toObject(); + m_authFactors = data.value("AuthFactors").toInt(); + qInfo() << "Auth factors changed:" << m_authFactors; + } + + QJsonDocument doc; + doc.setObject(retObj); + return doc.toJson(); +} + +void LoginModule::slotIdentifyStatus(const QString &name, const int errorCode, const QString &msg) +{ + qInfo() << "Handle identify status, user name: " << name << ", errorCode: " << errorCode << ", msg: " << msg; + m_waitAcceptSignalTimer->stop(); + if(m_IdentifyWithMultipleUserStarted){ + stopIdentify(); + } + + m_IdentifyWithMultipleUserStarted = false; + m_isAcceptFingerprintSignal = true; + m_lastAuthResult = AuthCallbackData(); + if (errorCode == 0) { + m_acceptSleepSignal = false; + + if (m_appType == AppType::Lock && m_userName != name && name != "") { + // 防止stop还未完成就开启了指纹认证 + QTimer::singleShot(30, this, [this] { + sendAuthTypeToSession(AuthType::AT_All); + }); + return ; + } + + m_lastAuthResult.account = name.isEmpty() ? m_userName : name; + m_lastAuthResult.result = AuthResult::Success; + if(m_authStatus == AuthStatus::Start || m_appType == AppType::Lock){ + sendAuthData(m_lastAuthResult); + } + } else { + // 发送一键登录失败的信息 + qWarning() << "Identify Status recive failed, error: " << msg; + QTimer::singleShot(30, this, [this] { + sendAuthTypeToSession(AuthType::AT_All); + }); + + m_lastAuthResult.result = AuthResult::Failure; + m_lastAuthResult.message = QString::number(errorCode); + m_lastAuthResult.account = name; + sendAuthData(m_lastAuthResult); + } +} + +void LoginModule::sendAuthData(AuthCallbackData& data) +{ + if (!m_authCallback) { + qWarning() << "Send auth data failed, callback is null"; + return; + } + + m_loginAuthenticated = true; + + if (m_spinner) { + m_spinner->stop(); + } + m_authCallback(&data, m_appData); + m_authStatus = AuthStatus::Finish; +} + +void LoginModule::slotPrepareForSleep(bool active) +{ + if (m_login1SessionSelf == nullptr) { + qWarning() << "Login1 session self is null"; + QDBusInterface login1Inter("org.freedesktop.login1", "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + QDBusConnection::systemBus()); + if(login1Inter.isValid()){ + QDBusPendingReply reply = login1Inter.call("GetSessionByPID" , uint(0)); + if(!reply.isError()){ + QString session_self = reply.value().path(); + m_login1SessionSelf = new QDBusInterface("org.freedesktop.login1", session_self, "org.freedesktop.login1.Session", QDBusConnection::systemBus()); + } else { + qWarning() << "Call `GetSessionByPID` failed, error: " << reply.error().message(); + } + + } else { + qDebug() << "Login1 interface is not valid"; + } + } + + if (m_login1SessionSelf == nullptr ) { + qWarning() << "Login1 session self is null"; + return; + } + + if (!m_login1SessionSelf->isValid()) { + qWarning() << "Login1 session self is not valid"; + return; + } + + bool isSessionActive = m_login1SessionSelf->property("Active").toBool(); + qInfo() << "Whether current session is active:" << isSessionActive; + m_lastAuthResult = AuthCallbackData(); + + // 休眠待机时,同时当前session被激活才开始调用一键登录指纹 + if (isSessionActive) { + m_acceptSleepSignal = true; + } + + if (active) { + m_lastAuthResult.result = AuthResult::Failure; + sendAuthData(m_lastAuthResult); + sendAuthTypeToSession(AuthType::AT_Custom); + return; + } + + if (isSessionActive) { + m_authStatus = AuthStatus::Start; + m_isAcceptFingerprintSignal = false; + m_loginAuthenticated = false; + sendAuthTypeToSession(AuthType::AT_Custom); + // 等待切换到插件认证完成后再发起多用户认证 + QTimer::singleShot(300, this, [this] { + startCallHuaweiFingerprint(); + }); + if (m_spinner) + m_spinner->start(); + } else { + //fix: 多用户时,第一个用户直接锁屏,然后待机唤醒,在直接切换到另一个用户时,m_login1SessionSelf没有激活,见159949 + sendAuthTypeToSession(AuthType::AT_All); + } +} + +void LoginModule::stopIdentify() +{ + QDBusMessage m = QDBusMessage::createMethodCall(DSS_DBUS::authenticateService, DSS_DBUS::fingerprintAuthPath, + DSS_DBUS::fingerprintAuthInterface, + "StopIdentifyWithMultipleUser"); + // 将消息发送到Dbus + QDBusMessage mes = QDBusConnection::systemBus().call(m); + if (mes.type() == QDBusMessage::ReplyMessage) { + qInfo() << "Stop identify success"; + } else { + qWarning() << "Stop identify failed, message type: " << mes.type(); + } +} + +void LoginModule::sendAuthTypeToSession(AuthType type) +{ + if (!m_messageCallback){ + qWarning() << "Callback message is null"; + m_needSendAuthType = true; + return; + } + + // 这里主要为了防止 在发送切换信号的时候,lightdm还为开启认证,导致切换类型失败 + if (m_authStatus == AuthStatus::None && !m_isLocked && type != AuthType::AT_Custom && m_appType != AppType::Lock) { + m_needSendAuthType = true; + return; + } + if (m_spinner && type != AuthType::AT_Custom) { + m_acceptSleepSignal = false; + m_spinner->stop(); + } + QJsonObject message; + message.insert("CmdType", "setAuthTypeInfo"); + QJsonObject retDataObj; + retDataObj["AuthType"] = static_cast(type); + message["Data"] = retDataObj; + QJsonDocument doc; + doc.setObject(message); + QString ret = m_messageCallback(doc.toJson(), m_appData); + // 解析返回值 + QJsonParseError jsonParseError; + const QJsonDocument retDoc = QJsonDocument::fromJson(ret.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || retDoc.isEmpty()) { + qWarning() << "Failed to analysis `SlotPrepareForSleep` info from shell, message callback: " << ret; + } + m_needSendAuthType = false; +} +} // namespace module +} // namespace dss diff --git a/plugins/one-key-login/login_module.h b/plugins/one-key-login/login_module.h new file mode 100644 index 00000000..3ab5f596 --- /dev/null +++ b/plugins/one-key-login/login_module.h @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGIN_MODULE_H +#define LOGIN_MODULE_H + +#include +#include +#include +#include + +#include "login_module_interface_v2.h" + +#include +#include + +DCORE_BEGIN_NAMESPACE +class DConfig; +DCORE_END_NAMESPACE + +namespace dss { +namespace module_v2 { + +class LoginModule : public QObject + , public LoginModuleInterfaceV2 +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules_v2.Login" FILE "login.json") + Q_INTERFACES(dss::module_v2::LoginModuleInterfaceV2) + + enum AuthStatus { + None, + Start, + Finish + }; + +public: + explicit LoginModule(QObject *parent = nullptr); + ~LoginModule() override; + + void init() override; + ModuleType type() const override { return LoginType; } + inline QString key() const override { return QStringLiteral("one-key-login"); } + inline QWidget *content() override { return m_loginWidget; } + inline LoadType loadPluginType() const override { return m_loadPluginType;} + void reset() override; + void setAppData(AppDataPtr) override; + void setAuthCallback(AuthCallbackFun) override; + void setMessageCallback(MessageCallbackFunc) override; + QString message(const QString&) override; + +public Q_SLOTS: + void slotIdentifyStatus(const QString &name, const int errorCode, const QString &msg); + void slotPrepareForSleep(bool active); + +private: + void initUI(); + void updateInfo(); + void initConnect(); + void startCallHuaweiFingerprint(); + void sendAuthTypeToSession(AuthType type); + void sendAuthData(AuthCallbackData& data); + void stopIdentify(); + +private: + AppDataPtr m_appData; + AuthCallbackFun m_authCallback; + MessageCallbackFunc m_messageCallback; + QWidget *m_loginWidget; + QString m_userName; + AppType m_appType; + LoadType m_loadPluginType; + bool m_isAcceptFingerprintSignal; + QTimer *m_waitAcceptSignalTimer; + DTK_CORE_NAMESPACE::DConfig *m_dconfig; + DTK_WIDGET_NAMESPACE::DSpinner *m_spinner; + bool m_acceptSleepSignal; + AuthCallbackData m_lastAuthResult; + AuthStatus m_authStatus; + bool m_needSendAuthType; + bool m_isLocked; + QDBusInterface* m_login1SessionSelf; + bool m_IdentifyWithMultipleUserStarted; + bool m_loginAuthenticated; // 登录界面是否已经验证过了 + int m_authFactors; +}; + +} // namespace module +} // namespace dss +#endif // LOGIN_MODULE_H diff --git a/resources.qrc b/resources.qrc index 0e9df32a..1bd61b33 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,5 +1,6 @@ + files/permission-interfaces/auth.json misc/images/caps_lock.svg misc/images/login_check.svg misc/images/login_lock.svg @@ -8,6 +9,7 @@ misc/images/password_hint.svg misc/images/select.svg misc/images/auth/face.svg + misc/images/auth/passkey.svg misc/images/auth/fingerprint.svg misc/images/auth/iris.svg misc/images/auth/password.svg @@ -25,5 +27,9 @@ misc/images/unlock/unlock_10.svg misc/images/retry16.svg misc/images/retry24.svg + misc/images/password-hide.svg + misc/images/password-shown.svg + misc/images/dss_warning.svg + misc/images/domainUser.svg diff --git a/scripts/lightdm-deepin-greeter b/scripts/lightdm-deepin-greeter deleted file mode 100755 index 43272e11..00000000 --- a/scripts/lightdm-deepin-greeter +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon" -if [ -x $display_daemon ]; then - $display_daemon & -fi -xsettingsd_conf="/etc/lightdm/deepin/xsettingsd.conf" -if [ -e $xsettingsd_conf ]; then - xsettingsd -c $xsettingsd_conf & -fi -/usr/bin/lightdm-deepin-greeter diff --git a/src/app/dde-lock.cpp b/src/app/dde-lock.cpp index 2d0881d0..62ba2b93 100644 --- a/src/app/dde-lock.cpp +++ b/src/app/dde-lock.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "accessibilitycheckerex.h" #include "appeventfilter.h" @@ -34,8 +13,11 @@ #include "lockworker.h" #include "modules_loader.h" #include "multiscreenmanager.h" -#include "propertygroup.h" #include "sessionbasemodel.h" +#include "warningcontent.h" +#include "plugin_manager.h" +#include "securityloaderhelper.h" +#include "dbusconstant.h" #include #include @@ -43,7 +25,6 @@ #include #include - #include DCORE_USE_NAMESPACE @@ -51,6 +32,13 @@ DWIDGET_USE_NAMESPACE int main(int argc, char *argv[]) { +#if (DTK_VERSION >= DTK_VERSION_CHECK(5, 6, 8, 7) && DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)) + DLogManager::registerLoggingRulesWatcher("org.deepin.dde.lock"); +#endif + + // 配置 qwebengine + configWebEngine(); + DApplication *app = nullptr; #if (DTK_VERSION < DTK_VERSION_CHECK(5, 4, 0, 0)) app = new DApplication(argc, argv); @@ -58,6 +46,8 @@ int main(int argc, char *argv[]) app = DApplication::globalApplication(argc, argv); #endif + // qt默认当最后一个窗口析构后,会自动退出程序,这里设置成false,防止插拔时,没有屏幕,导致进程退出 + QApplication::setQuitOnLastWindowClosed(false); //解决Qt在Retina屏幕上图片模糊问题 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); app->setOrganizationName("deepin"); @@ -68,7 +58,9 @@ int main(int argc, char *argv[]) AppEventFilter appEventFilter; app->installEventFilter(&appEventFilter); setAppType(APP_TYPE_LOCK); + qApp->setProperty("dssAppType", APP_TYPE_LOCK); + DGuiApplicationHelper::instance()->setSizeMode(DGuiApplicationHelper::SizeMode::NormalMode); DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::LightType); DPalette pa = DGuiApplicationHelper::instance()->applicationPalette(); pa.setColor(QPalette::Normal, DPalette::WindowText, QColor("#FFFFFF")); @@ -88,20 +80,17 @@ int main(int argc, char *argv[]) DGuiApplicationHelper::instance()->setApplicationPalette(pa); // follow system active color - QObject::connect(DGuiApplicationHelper::instance()->systemTheme(), &DPlatformTheme::activeColorChanged, [] (const QColor &color) { + QObject::connect(DGuiApplicationHelper::instance()->systemTheme(), &DPlatformTheme::activeColorChanged, [](const QColor &color) { auto palette = DGuiApplicationHelper::instance()->applicationPalette(); palette.setColor(QPalette::Highlight, color); DGuiApplicationHelper::instance()->setApplicationPalette(palette); }); + DLogManager::setLogFormat("%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [ %{function:-35} %{line}] %{message}\n"); +#ifdef QT_DEBUG DLogManager::registerConsoleAppender(); - DLogManager::registerFileAppender(); - - /* load translation files */ - loadTranslation(QLocale::system().name()); - - dss::module::ModulesLoader *modulesLoader = &dss::module::ModulesLoader::instance(); - modulesLoader->start(QThread::LowestPriority); +#endif + DLogManager::registerJournalAppender(); QCommandLineParser cmdParser; cmdParser.addHelpOption(); @@ -115,16 +104,29 @@ int main(int argc, char *argv[]) QCommandLineOption shutdown(QStringList() << "t" << "shutdown", "show shut down"); cmdParser.addOption(shutdown); - QCommandLineOption lockscreen(QStringList() << "l" << "lockscreen", "show lock screen"); - cmdParser.addOption(lockscreen); + QCommandLineOption lockScreen(QStringList() << "l" << "lockscreen", "show lock screen"); + cmdParser.addOption(lockScreen); + + QCommandLineOption quickLoginProcess(QStringList() << "q" << "quicklogin", "show for quick login"); + cmdParser.addOption(quickLoginProcess); + + QCommandLineOption fd1Opt("fd1", "fd1 from security loader", "fd1"); + cmdParser.addOption(fd1Opt); + QCommandLineOption fd2Opt("fd2", "fd2 from security loader", "fd2"); + cmdParser.addOption(fd2Opt); QStringList xddd = app->arguments(); cmdParser.process(*app); + int fd1 = cmdParser.isSet(fd1Opt) ? cmdParser.value(fd1Opt).toInt() : -1; + int fd2 = cmdParser.isSet(fd2Opt) ? cmdParser.value(fd2Opt).toInt() : -1; + SecurityLoaderHelper::instance().doSecurityLoader(fd1, fd2); + bool runDaemon = cmdParser.isSet(backend); bool showUserList = cmdParser.isSet(switchUser); bool showShutdown = cmdParser.isSet(shutdown); - bool showLockScreen = cmdParser.isSet(lockscreen); + bool showLockScreen = cmdParser.isSet(lockScreen); + bool isQuickLoginProcess= cmdParser.isSet(quickLoginProcess); #ifdef QT_DEBUG showLockScreen = true; @@ -132,9 +134,10 @@ int main(int argc, char *argv[]) SessionBaseModel *model = new SessionBaseModel(); model->setAppType(Lock); + //是否为快速登录拉起判断 + model->setQuickLoginProcess(isQuickLoginProcess); LockWorker *worker = new LockWorker(model); QObject::connect(&appEventFilter, &AppEventFilter::userIsActive, worker, &LockWorker::restartResetSessionTimer); - PropertyGroup *property_group = new PropertyGroup(worker); if (worker->isLocked()) { //如果当前Session被锁定,则启动dde-lock时直接进入锁屏状态 @@ -143,8 +146,6 @@ int main(int argc, char *argv[]) showLockScreen = true; } - property_group->addProperty("contentVisible"); - DBusLockAgent lockAgent; lockAgent.setModel(model); DBusLockFrontService lockService(&lockAgent); @@ -153,35 +154,107 @@ int main(int argc, char *argv[]) shutdownAgent.setModel(model); DBusShutdownFrontService shutdownServices(&shutdownAgent); - auto createFrame = [&] (QScreen *screen, int count) -> QWidget* { + // 这里提前进行单实例判断,避免后面数据初始化后再进行单实例判断而导致各种问题(例如:多次调用LockContent::instance()->init(model) 导致的localserver失效) + auto isSingle = app->setSingleInstance(QString("dde-lock%1").arg(getuid()), DApplication::UserScope); + QDBusConnection conn = QDBusConnection::sessionBus(); + if (!conn.registerService(DSS_DBUS::lockFrontService) || + !conn.registerObject(DSS_DBUS::lockFrontPath, &lockAgent) || + !conn.registerService(DSS_DBUS::shutdownService) || + !conn.registerObject(DSS_DBUS::shutdownPath, &shutdownAgent) || + !isSingle) { + qCWarning(DDE_SHELL) << "Register DBus failed, maybe lock front is running, error: " << conn.lastError(); + + if (!runDaemon) { + if (showUserList) { + QDBusInterface ifc(DSS_DBUS::lockFrontService, DSS_DBUS::lockFrontPath, DSS_DBUS::lockFrontService, QDBusConnection::sessionBus(), nullptr); + ifc.asyncCall("ShowUserList"); + } else if (showShutdown) { + QDBusInterface ifc(DSS_DBUS::shutdownService, DSS_DBUS::shutdownPath, DSS_DBUS::shutdownService, QDBusConnection::sessionBus(), nullptr); + ifc.asyncCall("Show"); + } else if (showLockScreen) { + do { + // 当前会话被锁定时,强制等待10ms后再获取一次锁定状态,如果变了直接退出,避免快速锁屏解锁时,lock状态未及时更新导致再启动dde-lock直接进入了锁屏状态,From bug: 200415 + if (worker->isLocked()) { + QThread::msleep(10); + if (!worker->isLocked()) + return 0; + } + } while (false); + + QDBusInterface ifc(DSS_DBUS::lockFrontService, DSS_DBUS::lockFrontPath, DSS_DBUS::lockFrontService, QDBusConnection::sessionBus(), nullptr); + ifc.asyncCall("Show"); + } + } + + return 0; + } + + /* load translation files */ + loadTranslation(QLocale::system().name()); + + ModulesLoader::instance().setLoadLoginModule(true); + ModulesLoader::instance().start(QThread::LowestPriority); + + PluginManager::instance()->setModel(model); + + LockContent::instance()->init(model); + WarningContent::instance()->setModel(model); + + QObject::connect(LockContent::instance(), &LockContent::requestSwitchToUser, worker, &LockWorker::switchToUser); + QObject::connect(LockContent::instance(), &LockContent::requestSetLayout, worker, &LockWorker::setKeyboardLayout); + QObject::connect(LockContent::instance(), &LockContent::requestStartAuthentication, worker, &LockWorker::startAuthentication); + QObject::connect(LockContent::instance(), &LockContent::sendTokenToAuth, worker, &LockWorker::sendTokenToAuth); + QObject::connect(LockContent::instance(), &LockContent::requestEndAuthentication, worker, &LockWorker::onEndAuthentication); + QObject::connect(LockContent::instance(), &LockContent::authFinished, worker, &LockWorker::authFinishedAction); + QObject::connect(LockContent::instance(), &LockContent::requestCheckAccount, worker, &LockWorker::checkAccount); + QObject::connect(LockContent::instance(), &LockContent::requestLockFrameHide, [model] { + model->setVisible(false); + }); + QObject::connect(LockContent::instance(), &LockContent::noPasswordLoginChanged, worker, &LockWorker::onNoPasswordLoginChanged); + QObject::connect(WarningContent::instance(), &WarningContent::requestLockFrameHide, [model] { + model->setVisible(false); + }); + QObject::connect(LockContent::instance(), &LockContent::requestLockStateChange, worker, &LockWorker::setLocked); + + auto createFrame = [&](QPointer screen, int count) -> QWidget* { LockFrame *lockFrame = new LockFrame(model); + // 创建Frame可能会花费数百毫秒,这个和机器性能有关,在此过程完成后,screen可能已经析构了 + // 在wayland的环境插拔屏幕或者显卡驱动有问题时可能会出现此类问题 + if (screen.isNull()) { + lockFrame->deleteLater(); + lockFrame = nullptr; + qCWarning(DDE_SHELL) << "Screen was released when the frame was created"; + return nullptr; + } lockFrame->setScreen(screen, count <= 0); - property_group->addObject(lockFrame); - QObject::connect(lockFrame, &LockFrame::requestSwitchToUser, worker, &LockWorker::switchToUser); - QObject::connect(model, &SessionBaseModel::visibleChanged, lockFrame, &LockFrame::setVisible); + QObject::connect(model, &SessionBaseModel::visibleChanged, lockFrame, [lockFrame](const bool visible) { + lockFrame->setVisible(visible); + QTimer::singleShot(300, lockFrame, [lockFrame] { + qCDebug(DDE_SHELL) << "Update frame after lock frame visible changed"; + lockFrame->update(); + }); + }); QObject::connect(model, &SessionBaseModel::visibleChanged, lockFrame,[&](bool visible) { emit lockService.Visible(visible); }); - QObject::connect(lockFrame, &LockFrame::requestSetLayout, worker, &LockWorker::setKeyboardLayout); + QObject::connect(model, &SessionBaseModel::onStatusChanged, lockFrame,[&](SessionBaseModel::ModeStatus status) { + emit shutdownServices.Visible(model->visible() && (status == SessionBaseModel::ModeStatus::PowerMode || status == SessionBaseModel::ModeStatus::ShutDownMode)); + }); QObject::connect(lockFrame, &LockFrame::requestEnableHotzone, worker, &LockWorker::enableZoneDetected, Qt::UniqueConnection); - QObject::connect(lockFrame, &LockFrame::destroyed, property_group, &PropertyGroup::removeObject); QObject::connect(lockFrame, &LockFrame::sendKeyValue, [&](QString key) { emit lockService.ChangKey(key); }); - QObject::connect(lockFrame, &LockFrame::requestStartAuthentication, worker, &LockWorker::startAuthentication); - QObject::connect(lockFrame, &LockFrame::sendTokenToAuth, worker, &LockWorker::sendTokenToAuth); - QObject::connect(lockFrame, &LockFrame::requestEndAuthentication, worker, &LockWorker::endAuthentication); - QObject::connect(lockFrame, &LockFrame::authFinished, worker, &LockWorker::onAuthFinished); if (model->isUseWayland()) { QObject::connect(lockFrame, &LockFrame::requestDisableGlobalShortcutsForWayland, worker, &LockWorker::disableGlobalShortcutsForWayland); } + lockFrame->setVisible(model->visible()); - emit lockService.Visible(true); + emit lockService.Visible(model->visible()); return lockFrame; }; MultiScreenManager multi_screen_manager; - multi_screen_manager.register_for_mutil_screen(createFrame); + multi_screen_manager.register_for_multi_screen(createFrame); #if defined(DSS_CHECK_ACCESSIBILITY) && defined(QT_DEBUG) AccessibilityCheckerEx checker; @@ -194,40 +267,18 @@ int main(int argc, char *argv[]) QObject::connect(model, &SessionBaseModel::visibleChanged, &multi_screen_manager, &MultiScreenManager::startRaiseContentFrame); - QDBusConnection conn = QDBusConnection::sessionBus(); - int ret = 0; - if (!conn.registerService(DBUS_LOCK_NAME) || - !conn.registerObject(DBUS_LOCK_PATH, &lockAgent) || - !conn.registerService(DBUS_SHUTDOWN_NAME) || - !conn.registerObject(DBUS_SHUTDOWN_PATH, &shutdownAgent) || - !app->setSingleInstance(QString("dde-lock%1").arg(getuid()), DApplication::UserScope)) { - qDebug() << "register dbus failed"<< "maybe lockFront is running..." << conn.lastError(); + // 加载Tray插件 + ModulesLoader::instance().setLoadLoginModule(false); + ModulesLoader::instance().start(QThread::LowestPriority); - if (!runDaemon) { - const char *lockFrontInter = "com.deepin.dde.lockFront"; - const char *shutdownFrontInter = "com.deepin.dde.shutdownFront"; - if (showUserList) { - QDBusInterface ifc(DBUS_LOCK_NAME, DBUS_LOCK_PATH, lockFrontInter, QDBusConnection::sessionBus(), nullptr); - ifc.asyncCall("ShowUserList"); - } else if (showShutdown) { - QDBusInterface ifc(DBUS_SHUTDOWN_NAME, DBUS_SHUTDOWN_PATH, shutdownFrontInter, QDBusConnection::sessionBus(), nullptr); - ifc.asyncCall("Show"); - } else if (showLockScreen) { - QDBusInterface ifc(DBUS_LOCK_NAME, DBUS_LOCK_PATH, lockFrontInter, QDBusConnection::sessionBus(), nullptr); - ifc.asyncCall("Show"); - } - } - } else { - if (!runDaemon) { - if (showUserList) { - emit model->showUserList(); - } else if (showShutdown) { - emit model->showShutdown(); - } else if (showLockScreen) { - emit model->showLockScreen(); - } + if (!runDaemon) { + if (showUserList) { + emit model->showUserList(); + } else if (showShutdown) { + emit model->showShutdown(); + } else if (showLockScreen) { + emit model->showLockScreen(); } - ret = app->exec(); } - return ret; + return app->exec(); } diff --git a/src/app/greeter-display-setting.cpp b/src/app/greeter-display-setting.cpp new file mode 100644 index 00000000..56a32f85 --- /dev/null +++ b/src/app/greeter-display-setting.cpp @@ -0,0 +1,310 @@ +// SPDX-FileCopyrightText: 2015 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "constants.h" +#include "dbusconstant.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +DCORE_USE_NAMESPACE + +Q_LOGGING_CATEGORY(DDE_SHELL, "org.deepin.dde.shell") + +const bool IsWayland = qgetenv("XDG_SESSION_TYPE").contains("wayland"); + +// Load system cursor --end + +bool isScaleConfigExists() { + QDBusInterface configInter(DSS_DBUS::systemDisplayService, + DSS_DBUS::systemDisplayPath, + DSS_DBUS::systemDisplayService, + QDBusConnection::systemBus()); + if (!configInter.isValid()) { + return false; + } + QDBusReply configReply = configInter.call("GetConfig"); + if (configReply.isValid()) { + QString config = configReply.value(); + QJsonParseError jsonError; + QJsonDocument jsonDoc(QJsonDocument::fromJson(config.toStdString().data(), &jsonError)); + if (jsonError.error == QJsonParseError::NoError) { + QJsonObject rootObj = jsonDoc.object(); + QJsonObject Config = rootObj.value("Config").toObject(); + return !Config.value("ScaleFactors").toObject().isEmpty(); + } else { + return false; + } + } else { + qCWarning(DDE_SHELL) << "Call `GetConfig` failed: " << configReply.error().message(); + return false; + } +} + +// 参照后端算法,保持一致 +float toListedScaleFactor(float s) { + const float min = 1.0, max = 3.0, step = 0.25; + if (s <= min) { + return min; + } else if (s >= max) { + return max; + } + + for (float i = min; i <= max; i += step) { + if (i > s) { + float ii = i - step; + float d1 = s - ii; + float d2 = i - s; + if (d1 >= d2) { + return i; + } else { + return ii; + } + } + } + return max; +} + +static double calcMaxScaleFactor(unsigned int width, unsigned int height) { + const QList scaleFactors = {1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0}; + + // 如果是竖屏,则反置width, height,防止计算的缩放有误 + if (width < height) { + std::swap(width, height); + } + + double maxWScale = width / 1024.0; + double maxHScale = height / 768.0; + + double maxValue = 0.0; + if (maxWScale < maxHScale) { + maxValue = maxWScale; + } else { + maxValue = maxHScale; + } + + if (maxValue > 3.0) { + maxValue = 3.0; + } + + double maxScale = 1.0; + for (int idx = 0; (idx*0.25 + 1.0) <= maxValue; idx++) { + maxScale = scaleFactors[idx]; + } + + return maxScale; +} + +static QStringList getScaleList() +{ + qDebug() << "Get scale list"; + Display *display = XOpenDisplay(nullptr); + if (!display) { + qWarning() << "Display is null"; + return QStringList{}; + } + + XRRScreenResources *resources = XRRGetScreenResourcesCurrent(display, DefaultRootWindow(display)); + if (!resources) { + resources = XRRGetScreenResources(display, DefaultRootWindow(display)); + qCWarning(DDE_SHELL) << "Get current XRR screen resources failed, instead of getting XRR screen resources, resources: " << resources; + } + + static const float MinScreenWidth = 1024.0f; + static const float MinScreenHeight = 768.0f; + static const QStringList tvstring = {"1.0", "1.25", "1.5", "1.75", "2.0", "2.25", "2.5", "2.75", "3.0"}; + QStringList fscaleList; + + if (resources) { + for (int i = 0; i < resources->noutput; i++) { + XRROutputInfo* outputInfo = XRRGetOutputInfo(display, resources, resources->outputs[i]); + if (outputInfo->crtc == 0 || outputInfo->mm_width == 0) + continue; + + XRRCrtcInfo *crtInfo = XRRGetCrtcInfo(display, resources, outputInfo->crtc); + if (crtInfo == nullptr) + continue; + + auto maxWScale = crtInfo->width / MinScreenWidth; + auto maxHScale = crtInfo->height / MinScreenHeight; + auto maxScale = maxWScale < maxHScale ? maxWScale : maxHScale; + maxScale = maxScale < 3.0f ? maxScale : 3.0f; + if (fscaleList.isEmpty()) { + for (int idx = 0; idx * 0.25f + 1.0f <= maxScale; ++idx) { + fscaleList << tvstring[idx]; + } + qDebug() << "First screen scale list:" << fscaleList; + } else { + QStringList tmpList; + for (int idx = 0; idx * 0.25f + 1.0f <= maxScale; ++idx) { + tmpList << tvstring[idx]; + } + qDebug() << "Current screen scale list:" << tmpList; + // fscaleList、tmpList两者取交集 + for (const auto &scale : fscaleList) { + if (!tmpList.contains(scale)) + fscaleList.removeAll(scale); + } + } + } + } else { + qCWarning(DDE_SHELL) << "Get scale factor failed, please check X11 Extension"; + } + + return fscaleList; +} + +static double getScaleFactor() { + Display *display = XOpenDisplay(nullptr); + double scaleFactor = 0.0; + + if (!display) { + return scaleFactor; + } + + XRRScreenResources *resources = XRRGetScreenResourcesCurrent(display, DefaultRootWindow(display)); + + if (!resources) { + resources = XRRGetScreenResources(display, DefaultRootWindow(display)); + qCWarning(DDE_SHELL) << "Get current XRR screen resources failed, instead of getting XRR screen resources, resources: " << resources; + } + + if (resources) { + double minScaleFactor = 3.0; + for (int i = 0; i < resources->noutput; i++) { + XRROutputInfo* outputInfo = XRRGetOutputInfo(display, resources, resources->outputs[i]); + if (outputInfo->crtc == 0 || outputInfo->mm_width == 0) continue; + + XRRCrtcInfo *crtInfo = XRRGetCrtcInfo(display, resources, outputInfo->crtc); + if (crtInfo == nullptr) continue; + // 参照后端的算法,与后端保持一致 + float lenPx = hypot(static_cast(crtInfo->width), static_cast(crtInfo->height)); + float lenMm = hypot(static_cast(outputInfo->mm_width), static_cast(outputInfo->mm_height)); + float lenPxStd = hypot(1920, 1080); + float lenMmStd = hypot(477, 268); + float fix = (lenMm - lenMmStd) * (lenPx / lenPxStd) * 0.00158; + if (fix > 0.5) { + fix = 0.5; + } + if (fix < -0.5) { + fix = -0.5; + } + float scale = (lenPx / lenMm) / (lenPxStd / lenMmStd) + fix; + scaleFactor = toListedScaleFactor(scale); + + double maxScaleFactor = calcMaxScaleFactor(crtInfo->width, crtInfo->height); + if (scaleFactor > maxScaleFactor) { + scaleFactor = maxScaleFactor; + } + if (minScaleFactor > scaleFactor) { + minScaleFactor = scaleFactor; + } + } + scaleFactor = scaleFactor > 0.0 ? minScaleFactor : 1; + } + else { + qCWarning(DDE_SHELL) << "Get scale factor failed, please check X11 Extension"; + } + + return scaleFactor; +} + +// 读取系统配置文件的缩放比,如果是null,默认返回1 +double getScaleFormConfig() +{ + double defaultScaleFactor = 1.0; + DTK_CORE_NAMESPACE::DConfig * dconfig = DConfig::create("org.deepin.dde.lightdm-deepin-greeter", "org.deepin.dde.lightdm-deepin-greeter", QString(), nullptr); + //华为机型,从override配置中获取默认缩放比 + if (dconfig) { + defaultScaleFactor = dconfig->value("defaultScaleFactors", 1.0).toDouble() ; + qDebug() <<"Default scale factor: " << defaultScaleFactor; + if(defaultScaleFactor < 1.0){ + defaultScaleFactor = 1.0; + } + + delete dconfig; + dconfig = nullptr; + } + + QDBusInterface configInter(DSS_DBUS::systemDisplayService, + DSS_DBUS::systemDisplayPath, + DSS_DBUS::systemDisplayService, + QDBusConnection::systemBus()); + if (!configInter.isValid()) { + return defaultScaleFactor; + } + QDBusReply configReply = configInter.call("GetConfig"); + if (configReply.isValid()) { + QString config = configReply.value(); + QJsonParseError jsonError; + QJsonDocument jsonDoc(QJsonDocument::fromJson(config.toLatin1(), &jsonError)); + if (jsonError.error == QJsonParseError::NoError) { + QJsonObject rootObj = jsonDoc.object(); + QJsonObject Config = rootObj.value("Config").toObject(); + double scaleFactor = Config.value("ScaleFactors").toObject().value("ALL").toDouble(); + qDebug() << "Scale factor from system display config: " << scaleFactor; + if(scaleFactor == 0.0) { + scaleFactor = defaultScaleFactor; + } else { + // 处理关机期间从高分屏换到低分屏的场景 + const auto &scales = getScaleList(); + qDebug() << "Scales:" << scales; + if (!scales.isEmpty() && !scales.contains(QString::number(scaleFactor, 'f', 2).replace("00", "0"))) { + qInfo() << "Scale factor is not in scales, use default scale factor"; + scaleFactor = defaultScaleFactor; + } + } + return scaleFactor; + } else { + return defaultScaleFactor; + } + } else { + qCWarning(DDE_SHELL) << "DBus call `GetConfig` failed, reply is invaild, error: " << configReply.error().message(); + return defaultScaleFactor; + } +} + +static void setQtScaleFactorEnv() { + double scaleFactor = 0.0; +#ifdef ENABLE_DSS_SNIPE + scaleFactor = getScaleFactor(); +#else + scaleFactor = IsWayland ? getScaleFormConfig() : getScaleFactor(); +#endif + qDebug() << "Final scale factor: " << scaleFactor; + if (scaleFactor > 0.0) { + std::cout << QString("QT_SCALE_FACTOR="+QByteArray::number(scaleFactor)).toStdString().c_str() << std::endl; + } else { + std::cout << QString("QT_AUTO_SCREEN_SCALE_FACTOR=1").toStdString().c_str() << std::endl; + } +} + +int main(int argc, char* argv[]) +{ + // x11下,dxcb设置Qt::AA_EnableHighDpiScaling属性后,平台插件会处理缩放,不需要再主动设置QT_SCALE_FACTOR,否则会导致缩放系数相乘,得出错误的qApp->devicePixelRatio() + // wayland下,dwayland平台插件不会处理缩放,需要手动设置QT_SCALE_FACTOR +#ifdef ENABLE_DSS_SNIPE + if (!IsWayland) { + setQtScaleFactorEnv(); + } +#else + if (IsWayland) { + setQtScaleFactorEnv(); + } +#endif + + return 0; +} diff --git a/src/app/lightdm-deepin-greeter.cpp b/src/app/lightdm-deepin-greeter.cpp index 33a8ddbc..3fa3b4f9 100644 --- a/src/app/lightdm-deepin-greeter.cpp +++ b/src/app/lightdm-deepin-greeter.cpp @@ -1,214 +1,41 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "accessibilitycheckerex.h" #include "appeventfilter.h" #include "constants.h" #include "greeterworker.h" +#include "logincontent.h" #include "loginwindow.h" #include "modules_loader.h" #include "multiscreenmanager.h" -#include "propertygroup.h" #include "sessionbasemodel.h" +#include "public_func.h" +#include "plugin_manager.h" +#ifndef ENABLE_DSS_SNIPE +#include +#endif #include #include #include -#include #include #include -#include +#include #include -#include #include -#include -#include -#include #include +#include + +#include "dbusconstant.h" DCORE_USE_NAMESPACE DWIDGET_USE_NAMESPACE -//Load the System cursor --begin -static XcursorImages* -xcLoadImages(const char *image, int size) -{ - QSettings settings(DDESESSIONCC::DEFAULT_CURSOR_THEME, QSettings::IniFormat); - //The default cursor theme path - qDebug() << "Theme Path:" << DDESESSIONCC::DEFAULT_CURSOR_THEME; - QString item = "Icon Theme"; - const char* defaultTheme = ""; - QVariant tmpCursorTheme = settings.value(item + "/Inherits"); - if (tmpCursorTheme.isNull()) { - qDebug() << "Set a default one instead, if get the cursor theme failed!"; - defaultTheme = "Deepin"; - } else { - defaultTheme = tmpCursorTheme.toString().toLocal8Bit().data(); - } - - qDebug() << "Get defaultTheme:" << tmpCursorTheme.isNull() - << defaultTheme; - return XcursorLibraryLoadImages(image, defaultTheme, size); -} - -static unsigned long loadCursorHandle(Display *dpy, const char *name, int size) -{ - if (size == -1) { - size = XcursorGetDefaultSize(dpy); - } - - // Load the cursor images - XcursorImages *images = nullptr; - images = xcLoadImages(name, size); - - if (!images) { - images = xcLoadImages(name, size); - if (!images) { - return 0; - } - } - - unsigned long handle = static_cast(XcursorImagesLoadCursor(dpy,images)); - XcursorImagesDestroy(images); - - return handle; -} - -static int set_rootwindow_cursor() { - Display* display = XOpenDisplay(nullptr); - if (!display) { - qDebug() << "Open display failed"; - return -1; - } - - const char *cursorPath = qApp->devicePixelRatio() > 1.7 - ? "/usr/share/icons/bloom/cursors/loginspinner@2x" - : "/usr/share/icons/bloom/cursors/loginspinner"; - - Cursor cursor = static_cast(XcursorFilenameLoadCursor(display, cursorPath)); - if (cursor == 0) { - cursor = static_cast(loadCursorHandle(display, "watch", 24)); - } - XDefineCursor(display, XDefaultRootWindow(display),cursor); - - // XFixesChangeCursorByName is the key to change the cursor - // and the XFreeCursor and XCloseDisplay is also essential. - - XFixesChangeCursorByName(display, cursor, "watch"); - - XFreeCursor(display, cursor); - XCloseDisplay(display); - - return 0; -} -// Load system cursor --end - -static double get_scale_ratio() { - Display *display = XOpenDisplay(nullptr); - double scaleRatio = 0.0; - - if (!display) { - return scaleRatio; - } - - XRRScreenResources *resources = XRRGetScreenResourcesCurrent(display, DefaultRootWindow(display)); - - if (!resources) { - resources = XRRGetScreenResources(display, DefaultRootWindow(display)); - qWarning() << "get XRRGetScreenResourcesCurrent failed, use XRRGetScreenResources."; - } - - if (resources) { - for (int i = 0; i < resources->noutput; i++) { - XRROutputInfo* outputInfo = XRRGetOutputInfo(display, resources, resources->outputs[i]); - if (outputInfo->crtc == 0 || outputInfo->mm_width == 0) continue; - - XRRCrtcInfo *crtInfo = XRRGetCrtcInfo(display, resources, outputInfo->crtc); - if (crtInfo == nullptr) continue; - - scaleRatio = static_cast(crtInfo->width) / static_cast(outputInfo->mm_width) / (1366.0 / 310.0); - - if (scaleRatio > 1 + 2.0 / 3.0) { - scaleRatio = 2; - } - else if (scaleRatio > 1 + 1.0 / 3.0) { - scaleRatio = 1.5; - } - else { - scaleRatio = 1; - } - } - } - else { - qWarning() << "get scale radio failed, please check X11 Extension."; - } - - return scaleRatio; -} - -static void set_auto_QT_SCALE_FACTOR() { - const double ratio = get_scale_ratio(); - if (ratio > 0.0) { - setenv("QT_SCALE_FACTOR", QByteArray::number(ratio).constData(), 1); - } - - if (!qEnvironmentVariableIsSet("QT_SCALE_FACTOR")) { - setenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1", 1); - } -} - -// 初次启动时,设置一下鼠标的默认位置 -void set_pointer() -{ - auto set_position = [ = ] (QPoint p) { - Display *dpy; - dpy = XOpenDisplay(nullptr); - - if (!dpy) return; - - Window root_window; - root_window = XRootWindow(dpy, 0); - XSelectInput(dpy, root_window, KeyReleaseMask); - XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, p.x(), p.y()); - XFlush(dpy); - }; - - if (!qApp->primaryScreen()) { - QObject::connect(qApp, &QGuiApplication::primaryScreenChanged, [ = ] { - static bool first = true; - if (first) { - set_position(qApp->primaryScreen()->geometry().center()); - first = false; - } - }); - } else { - set_position(qApp->primaryScreen()->geometry().center()); - } -} +const bool IsWayland = qgetenv("XDG_SESSION_TYPE").contains("wayland"); int main(int argc, char* argv[]) { @@ -218,26 +45,39 @@ int main(int argc, char* argv[]) setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); } + // 配置 qwebengine + configWebEngine(); + DGuiApplicationHelper::setAttribute(DGuiApplicationHelper::UseInactiveColorGroup, false); - // 设置缩放,文件存在的情况下,由后端去设置,否则前端自行设置 - if (!QFile::exists("/etc/lightdm/deepin/xsettingsd.conf")) { - set_auto_QT_SCALE_FACTOR(); - } + + // 以下4行为解决登录和锁屏的默认字体不一致的情况,gsettings默认值为10.5, + // 而登录读取不到gsettings配置的默认值而使用Qt默认的9,导致登录界面字体很小。 + // bug:161915 + QFont font; + font.setPointSize(10.5); + font.setFamily("Noto Sans CJK SC-Thin"); + qGuiApp->setFont(font); DApplication a(argc, argv); + +#ifndef ENABLE_DSS_SNIPE + DDE_EventLogger::EventLogger::instance().init("org.deepin.dde.lightdm-deepin-greeter", false); +#endif + // qt默认当最后一个窗口析构后,会自动退出程序,这里设置成false,防止插拔时,没有屏幕,导致进程退出 + QApplication::setQuitOnLastWindowClosed(false); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); qApp->setOrganizationName("deepin"); qApp->setApplicationName("org.deepin.dde.lightdm-deepin-greeter"); - qApp->setApplicationVersion("2015.1.0"); - qApp->setAttribute(Qt::AA_ForceRasterWidgets); - set_pointer(); + setPointer(); //注册全局事件过滤器 AppEventFilter appEventFilter; a.installEventFilter(&appEventFilter); setAppType(APP_TYPE_LOGIN); + qApp->setProperty("dssAppType", APP_TYPE_LOGIN); + DGuiApplicationHelper::instance()->setSizeMode(DGuiApplicationHelper::SizeMode::NormalMode); DPalette pa = DGuiApplicationHelper::instance()->standardPalette(DGuiApplicationHelper::LightType); pa.setColor(QPalette::Normal, DPalette::WindowText, QColor("#FFFFFF")); pa.setColor(QPalette::Normal, DPalette::Text, QColor("#FFFFFF")); @@ -255,35 +95,36 @@ int main(int argc, char* argv[]) DGuiApplicationHelper::generatePaletteColor(pa, DPalette::ButtonText, DGuiApplicationHelper::LightType); DGuiApplicationHelper::instance()->setApplicationPalette(pa); + DLogManager::setLogFormat("%{time}{yyyy-MM-dd, HH:mm:ss.zzz} [%{type:-7}] [ %{function:-35} %{line}] %{message}\n"); DLogManager::registerConsoleAppender(); + DLogManager::registerJournalAppender(); - dss::module::ModulesLoader *modulesLoader = &dss::module::ModulesLoader::instance(); - modulesLoader->start(QThread::LowestPriority); - - const QString serviceName = "com.deepin.daemon.Accounts"; QDBusConnectionInterface *interface = QDBusConnection::systemBus().interface(); - if (!interface->isServiceRegistered(serviceName)) { - qWarning() << "accounts service is not registered wait..."; - - QDBusServiceWatcher *serviceWatcher = new QDBusServiceWatcher(serviceName, QDBusConnection::systemBus()); - QObject::connect(serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, [ = ] (const QString &service) { - if (service == serviceName) { - qCritical() << "ERROR, accounts service unregistered, what should I do?"; + if (!interface->isServiceRegistered(DSS_DBUS::accountsService)) { + qCWarning(DDE_SHELL) << "Accounts service is not registered wait..."; + QDBusServiceWatcher *serviceWatcher = new QDBusServiceWatcher(DSS_DBUS::accountsService, QDBusConnection::systemBus()); + QObject::connect(serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, [](const QString &service) { + if (service == DSS_DBUS::accountsService) { + qCritical() << "ERROR: accounts service unregistered"; } }); #ifdef ENABLE_WAITING_ACCOUNTS_SERVICE - qDebug() << "waiting for deepin accounts service"; + qDebug() << "Waiting for deepin accounts service"; QEventLoop eventLoop; QObject::connect(serviceWatcher, &QDBusServiceWatcher::serviceRegistered, &eventLoop, &QEventLoop::quit); #ifdef QT_DEBUG QTimer::singleShot(10000, &eventLoop, &QEventLoop::quit); #endif eventLoop.exec(); - qDebug() << "service registered!"; + qDebug() << "Service registered!"; #endif } + // 加载login模块 + ModulesLoader::instance().setLoadLoginModule(true); + ModulesLoader::instance().start(QThread::LowestPriority); + SessionBaseModel *model = new SessionBaseModel(); model->setAppType(Login); GreeterWorker *worker = new GreeterWorker(model); @@ -292,34 +133,46 @@ int main(int argc, char* argv[]) /* load translation files */ loadTranslation(model->currentUser()->locale()); + PluginManager::instance()->setModel(model); + // 设置系统登录成功的加载光标 - QObject::connect(model, &SessionBaseModel::authFinished, model, [ = ](bool is_success) { - if (is_success) - set_rootwindow_cursor(); + QObject::connect(model, &SessionBaseModel::authFinished, model, [=](bool isSuccess) { + if (isSuccess) + setRootWindowCursor(); }); - // 保证多个屏幕的情况下,始终只有一个屏幕显示 - PropertyGroup *property_group = new PropertyGroup(worker); - property_group->addProperty("contentVisible"); - + // 初始化LoginContent + LoginContent::instance()->init(model); + QObject::connect(LoginContent::instance(), &LoginContent::requestSwitchToUser, worker, &GreeterWorker::switchToUser); + QObject::connect(LoginContent::instance(), &LoginContent::requestSetLayout, worker, &GreeterWorker::setKeyboardLayout); + QObject::connect(LoginContent::instance(), &LoginContent::requestCheckAccount, worker, &GreeterWorker::checkAccount); + QObject::connect(LoginContent::instance(), &LoginContent::requestCheckSameNameAccount, worker, &GreeterWorker::checkSameNameAccount); + QObject::connect(worker, &GreeterWorker::requestShowUsersWithTheSameName, LoginContent::instance(), &LoginContent::showUsersWithTheSameName); + QObject::connect(LoginContent::instance(), &LoginContent::requestStartAuthentication, worker, &GreeterWorker::startAuthentication); + QObject::connect(LoginContent::instance(), &LoginContent::sendTokenToAuth, worker, &GreeterWorker::sendTokenToAuth); + QObject::connect(LoginContent::instance(), &LoginContent::requestEndAuthentication, worker, &GreeterWorker::endAuthentication); + QObject::connect(LoginContent::instance(), &LoginContent::authFinished, worker, &GreeterWorker::onAuthFinished); + QObject::connect(LoginContent::instance(), &LoginContent::noPasswordLoginChanged, worker, &GreeterWorker::onNoPasswordLoginChanged); + + // 根据屏幕创建全屏背景窗口 auto createFrame = [&](QPointer screen, int count) -> QWidget * { LoginWindow *loginFrame = new LoginWindow(model); + // 创建Frame可能会花费数百毫秒,这个和机器性能有关,在此过程完成后,screen可能已经析构了 + // 在wayland的环境插拔屏幕或者显卡驱动有问题时可能会出现此类问题 + if (screen.isNull()) { + loginFrame->deleteLater(); + loginFrame = nullptr; + qCWarning(DDE_SHELL) << "Screen was released when the frame was created"; + return nullptr; + } loginFrame->setScreen(screen, count <= 0); - property_group->addObject(loginFrame); - QObject::connect(loginFrame, &LoginWindow::requestSwitchToUser, worker, &GreeterWorker::switchToUser); - QObject::connect(loginFrame, &LoginWindow::requestSetKeyboardLayout, worker, &GreeterWorker::setKeyboardLayout); - QObject::connect(loginFrame, &LoginWindow::requestCheckAccount, worker, &GreeterWorker::checkAccount); - QObject::connect(loginFrame, &LoginWindow::requestStartAuthentication, worker, &GreeterWorker::startAuthentication); - QObject::connect(loginFrame, &LoginWindow::sendTokenToAuth, worker, &GreeterWorker::sendTokenToAuth); - QObject::connect(loginFrame, &LoginWindow::requestEndAuthentication, worker, &GreeterWorker::endAuthentication); - QObject::connect(loginFrame, &LoginWindow::authFinished, worker, &GreeterWorker::onAuthFinished); QObject::connect(worker, &GreeterWorker::requestUpdateBackground, loginFrame, &LoginWindow::updateBackground); - loginFrame->show(); + loginFrame->setVisible(model->visible()); return loginFrame; }; MultiScreenManager multi_screen_manager; - multi_screen_manager.register_for_mutil_screen(createFrame); + multi_screen_manager.register_for_multi_screen(createFrame); QObject::connect(model, &SessionBaseModel::visibleChanged, &multi_screen_manager, &MultiScreenManager::startRaiseContentFrame); #if defined(DSS_CHECK_ACCESSIBILITY) && defined(QT_DEBUG) @@ -329,6 +182,11 @@ int main(int argc, char* argv[]) checker.setOutputFormat(DAccessibilityChecker::FullFormat); checker.start(); #endif + model->setVisible(true); + + // 加载非login模块 + ModulesLoader::instance().setLoadLoginModule(false); + ModulesLoader::instance().start(QThread::LowestPriority); return a.exec(); } diff --git a/src/dde-lock/dbus/dbuslockagent.cpp b/src/dde-lock/dbus/dbuslockagent.cpp index f9e51301..e0a1cc44 100644 --- a/src/dde-lock/dbus/dbuslockagent.cpp +++ b/src/dde-lock/dbus/dbuslockagent.cpp @@ -1,5 +1,12 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "dbuslockagent.h" #include "sessionbasemodel.h" +#include "dbusconstant.h" + +#include DBusLockAgent::DBusLockAgent(QObject *parent) : QObject(parent), m_model(nullptr) { @@ -13,13 +20,28 @@ void DBusLockAgent::setModel(SessionBaseModel *const model) void DBusLockAgent::Show() { + getCallerBySender(); + + if (isUpdating()) + return; + m_model->setIsBlackMode(false); m_model->setIsHibernateModel(false); m_model->setVisible(true); } +bool DBusLockAgent::Visible() const +{ + return m_model->visible(); +} + void DBusLockAgent::ShowAuth(bool active) { + getCallerBySender(); + + if (isUpdating()) + return; + Show(); m_model->activeAuthChanged(active); } @@ -27,11 +49,17 @@ void DBusLockAgent::ShowAuth(bool active) // 待机,enable=true:进入待机;enable=false:待机恢复 void DBusLockAgent::Suspend(bool enable) { + getCallerBySender(); + + qCInfo(DDE_SHELL) << (enable ? "Enter suspend" : "Suspend recovery"); + if (isUpdating()) + return; + if (enable) { m_model->setIsBlackMode(true); m_model->setVisible(true); } else { - QDBusInterface infc("com.deepin.daemon.Power","/com/deepin/daemon/Power","com.deepin.daemon.Power"); + QDBusInterface infc(DSS_DBUS::sessionPowerService, DSS_DBUS::sessionPowerPath,DSS_DBUS::sessionPowerService); // 待机恢复需要密码 bool bSuspendLock = infc.property("SleepLock").toBool(); @@ -47,11 +75,114 @@ void DBusLockAgent::Suspend(bool enable) void DBusLockAgent::Hibernate(bool enable) { + getCallerBySender(); + + qCInfo(DDE_SHELL) << (enable ? "Enter hibernate" : "Hibernate recovery"); + if (isUpdating()) + return; + m_model->setIsHibernateModel(enable); m_model->setVisible(true); } void DBusLockAgent::ShowUserList() { + getCallerBySender(); + + if (isUpdating()) + return; + emit m_model->showUserList(); } + +/** + * @brief 如果处于更新状态,那么不响应shutdown接口 + */ +bool DBusLockAgent::isUpdating() const +{ + const bool updating = m_model->currentContentType() == SessionBaseModel::UpdateContent; + return updating; +} + +void DBusLockAgent::getPathByPid(quint32 pid) +{ + if (pid <= 0) { + return; + } + + QString cmdlinePath = QString("/proc/%1/cmdline").arg(pid); + if (QFile::exists(cmdlinePath)) { + QFile file(cmdlinePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QByteArray line = file.readAll().trimmed(); + QString path = QString::fromLocal8Bit(line.split(' ').last()); + qWarning() << "Caller path : " << path; + } + } +} + +void DBusLockAgent::getPPidByPid(quint32 pid) +{ + if (pid <= 0) { + return; + } + + QString statusFilePath = QString("/proc/%1/status").arg(pid); + if (!QFile::exists(statusFilePath)) { + qWarning() << " File not exists :" <= QT_VERSION_CHECK(6, 0, 0) + textStream.setEncoding(QStringConverter::Utf8); +#else + textStream.setCodec("UTF-8"); +#endif + while (!textStream.atEnd()) { + QString line = textStream.readLine(); + if (line.startsWith("PPid:")) { + QStringList parts = line.split(QChar(':')); + if (parts.size() > 1) { + bool ok = false; + quint32 ppid = parts.at(1).trimmed().toInt(&ok); + if (ok) { + getPathByPid(ppid); + getPPidByPid(ppid); + } + } + } + } +} + +void DBusLockAgent::getCallerBySender() +{ + QDBusMessage msg = message(); + + if (msg.type() == QDBusMessage::MethodCallMessage) { + QString caller = msg.service(); + if (!caller.isEmpty()) { + QDBusInterface dbusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus()); + // 调用 GetConnectionUnixProcessID 方法查询 PID + QDBusReply reply = dbusInterface.call("GetConnectionUnixProcessID", caller); + if (reply.isValid()) { + quint32 pid = reply.value(); + qWarning() << "Caller Pid :" << pid; + + getPathByPid(pid); + getPPidByPid(pid); + } else { + qWarning() << "Get caller pid failed :" << reply.error().message(); + } + } + } +} diff --git a/src/dde-lock/dbus/dbuslockagent.h b/src/dde-lock/dbus/dbuslockagent.h index f162363c..e869ae82 100644 --- a/src/dde-lock/dbus/dbuslockagent.h +++ b/src/dde-lock/dbus/dbuslockagent.h @@ -1,10 +1,15 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef DBUSLOCKAGENT_H #define DBUSLOCKAGENT_H #include +#include class SessionBaseModel; -class DBusLockAgent : public QObject +class DBusLockAgent : public QObject, protected QDBusContext { Q_OBJECT public: @@ -16,6 +21,14 @@ class DBusLockAgent : public QObject void ShowAuth(bool active); void Suspend(bool enable); void Hibernate(bool enable); + bool Visible() const; + +private: + bool isUpdating() const; + + void getPathByPid(quint32 pid); + void getPPidByPid(quint32 pid); + void getCallerBySender(); private: SessionBaseModel *m_model; diff --git a/src/dde-lock/dbus/dbuslockfrontservice.cpp b/src/dde-lock/dbus/dbuslockfrontservice.cpp index 29f9468e..e8029865 100644 --- a/src/dde-lock/dbus/dbuslockfrontservice.cpp +++ b/src/dde-lock/dbus/dbuslockfrontservice.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbuslockfrontservice.h" @@ -39,6 +18,11 @@ DBusLockFrontService::~DBusLockFrontService() { } +bool DBusLockFrontService::visible() const +{ + return parent()->Visible(); +} + void DBusLockFrontService::Show() { parent()->Show(); diff --git a/src/dde-lock/dbus/dbuslockfrontservice.h b/src/dde-lock/dbus/dbuslockfrontservice.h index bf762c0c..609bb929 100644 --- a/src/dde-lock/dbus/dbuslockfrontservice.h +++ b/src/dde-lock/dbus/dbuslockfrontservice.h @@ -1,52 +1,35 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSLOCKFRONTSERVICE_H #define DBUSLOCKFRONTSERVICE_H #include "dbuslockagent.h" + #include -#include -#include QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; -class QStringList; class QVariant; QT_END_NAMESPACE +const QString lockFrontService = "org.deepin.dde.LockFront1"; + /* * Proxy class for interface com.deepin.dde.lockFront */ class DBusLockFrontService: public QDBusAbstractAdaptor { Q_OBJECT +#ifndef ENABLE_DSS_SNIPE Q_CLASSINFO("D-Bus Interface", "com.deepin.dde.lockFront") +#else + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.LockFront1") +#endif public: explicit DBusLockFrontService(DBusLockAgent *parent); @@ -55,7 +38,11 @@ class DBusLockFrontService: public QDBusAbstractAdaptor inline DBusLockAgent *parent() const { return static_cast(QObject::parent()); } -public:// PROPERTIES +public: // PROPERTIES + Q_PROPERTY(bool Visible READ visible) + + bool visible() const; + public Q_SLOTS:// METHODS void Show(); void ShowUserList(); diff --git a/src/dde-lock/dbus/dbusshutdownagent.cpp b/src/dde-lock/dbus/dbusshutdownagent.cpp index 245e273e..2dc37ac4 100644 --- a/src/dde-lock/dbus/dbusshutdownagent.cpp +++ b/src/dde-lock/dbus/dbusshutdownagent.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2020 Uniontech Technology Co., Ltd. - * - * Author: chenjun - * - * Maintainer: chenjun - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbusshutdownagent.h" #include "sessionbasemodel.h" @@ -36,9 +19,10 @@ void DBusShutdownAgent::setModel(SessionBaseModel * const model) void DBusShutdownAgent::show() { - if (!canShowShutDown()) { + getCallerBySender(); + + if (isUpdating() || !canShowShutDown()) return; - } m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); m_model->setVisible(true); @@ -46,7 +30,13 @@ void DBusShutdownAgent::show() void DBusShutdownAgent::Shutdown() { - qInfo() << "Shutdown"; + qCInfo(DDE_SHELL) << "Shutdown"; + + getCallerBySender(); + + if (isUpdating()) + return; + if (!canShowShutDown()) { //锁屏时允许关机 emit m_model->onRequirePowerAction(SessionBaseModel::PowerAction::RequireShutdown, false); @@ -57,9 +47,29 @@ void DBusShutdownAgent::Shutdown() } } +void DBusShutdownAgent::UpdateAndShutdown() +{ + qCInfo(DDE_SHELL) << "Update and shutdown"; + + getCallerBySender(); + + if (isUpdating()) + return; + + m_model->setUpdatePowerMode(SessionBaseModel::UPM_UpdateAndShutdown); + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); + m_model->setVisible(true); +} + void DBusShutdownAgent::Restart() { - qInfo() << "Restart"; + qCInfo(DDE_SHELL) << "Restart"; + + getCallerBySender(); + + if (isUpdating()) + return; + if (!canShowShutDown()) { //锁屏时允许重启 emit m_model->onRequirePowerAction(SessionBaseModel::PowerAction::RequireRestart, false); @@ -70,12 +80,28 @@ void DBusShutdownAgent::Restart() } } +void DBusShutdownAgent::UpdateAndReboot() +{ + qCInfo(DDE_SHELL) << "Update and reboot"; + + getCallerBySender(); + + if (isUpdating()) + return; + + m_model->setUpdatePowerMode(SessionBaseModel::UPM_UpdateAndReboot); + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); + m_model->setVisible(true); +} + void DBusShutdownAgent::Logout() { - qInfo() << "Logout"; - if (!canShowShutDown()) { + qCInfo(DDE_SHELL) << "Logout"; + + getCallerBySender(); + + if (isUpdating() || !canShowShutDown()) return; - } m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); m_model->setVisible(true); @@ -84,57 +110,186 @@ void DBusShutdownAgent::Logout() void DBusShutdownAgent::Suspend() { - qInfo() << "Suspend"; + qCInfo(DDE_SHELL) << "Suspend"; + + getCallerBySender(); + + if (isUpdating()) + return; + if (!canShowShutDown()) { - //锁屏时允许待机 + // 锁屏时允许待机 m_model->setPowerAction(SessionBaseModel::RequireSuspend); } else { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); - m_model->setVisible(true); +#ifndef ENABLE_DSS_SNIPE + if (m_model->getPowerGSettings("", "sleepLock").toBool()) { +#else + if (isSleepLock()) { +#endif + m_model->setVisible(true); + } emit m_model->onRequirePowerAction(SessionBaseModel::RequireSuspend, true); } } void DBusShutdownAgent::Hibernate() { - qInfo() << "Hibernate"; + qCInfo(DDE_SHELL) << "Hibernate"; + + getCallerBySender(); + + if (isUpdating()) + return; + if (!canShowShutDown()) { - //锁屏时允许休眠 + // 锁屏时允许休眠 m_model->setPowerAction(SessionBaseModel::RequireHibernate); } else { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); - m_model->setVisible(true); +#ifndef ENABLE_DSS_SNIPE + if (m_model->getPowerGSettings("", "sleepLock").toBool()) { +#else + if (isSleepLock()) { +#endif + m_model->setVisible(true); + } emit m_model->onRequirePowerAction(SessionBaseModel::RequireHibernate, true); } } void DBusShutdownAgent::SwitchUser() { - qInfo() << "SwitchUser"; - if (!canShowShutDown()) { + qCInfo(DDE_SHELL) << "Switch user"; + + getCallerBySender(); + + if (isUpdating() || !canShowShutDown()) return; - } emit m_model->showUserList(); } void DBusShutdownAgent::Lock() { - qInfo() << "Lock"; - if (!canShowShutDown()) { + qCInfo(DDE_SHELL) << "Lock"; + + getCallerBySender(); + + if (isUpdating() || !canShowShutDown()) return; - } + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); m_model->setVisible(true); m_model->setPowerAction(SessionBaseModel::RequireLock); } -bool DBusShutdownAgent::canShowShutDown() +bool DBusShutdownAgent::canShowShutDown() const +{ + // 如果当前界面已显示,而且不是关机模式,则当前已锁屏,因此不允许调用,以免在锁屏时被远程调用而进入桌面 + qCInfo(DDE_SHELL) << "Can show shutdown, visible: " << m_model->visible() << ", mode: " << m_model->currentModeState(); + + return !(m_model->visible() && m_model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode); +} + +/** + * @brief 如果处于更新状态,那么不响应shutdown接口 + */ +bool DBusShutdownAgent::isUpdating() const +{ + qCInfo(DDE_SHELL) << "DBus shutdown agent is updating, current content type: " << m_model->currentContentType(); + return m_model->currentContentType() == SessionBaseModel::UpdateContent; +} + +void DBusShutdownAgent::getPathByPid(quint32 pid) +{ + if (pid <= 0) { + return; + } + + QString cmdlinePath = QString("/proc/%1/cmdline").arg(pid); + if (QFile::exists(cmdlinePath)) { + QFile file(cmdlinePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QByteArray line = file.readAll().trimmed(); + QString path = QString::fromLocal8Bit(line.split(' ').last()); + qWarning() << "Caller path : " << path; + } + } +} + +void DBusShutdownAgent::getPPidByPid(quint32 pid) +{ + if (pid <= 0) { + return; + } + + QString statusFilePath = QString("/proc/%1/status").arg(pid); + if (!QFile::exists(statusFilePath)) { + qWarning() << " File not exists :" <= QT_VERSION_CHECK(6, 0, 0) + textStream.setEncoding(QStringConverter::Utf8); +#else + textStream.setCodec("UTF-8"); +#endif + while (!textStream.atEnd()) { + QString line = textStream.readLine(); + if (line.startsWith("PPid:")) { + QStringList parts = line.split(QChar(':')); + if (parts.size() > 1) { + bool ok = false; + quint32 ppid = parts.at(1).trimmed().toInt(&ok); + if (ok) { + getPathByPid(ppid); + getPPidByPid(ppid); + } + } + } + } +} + +void DBusShutdownAgent::getCallerBySender() { - //如果当前界面已显示,而且不是关机模式,则当前已锁屏,因此不允许调用,以免在锁屏时被远程调用而进入桌面 - if (m_model->visible() && m_model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode) { - return false; + QString DDE_DEBUG_LEVEL = qgetenv("DDE_DEBUG_LEVEL"); + if ( DDE_DEBUG_LEVEL.toLower() != "debug") { + return; } - return true; + QDBusMessage msg = message(); + + if (msg.type() == QDBusMessage::MethodCallMessage) { + QString caller = msg.service(); + if (!caller.isEmpty()) { + QDBusInterface dbusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus()); + // 调用 GetConnectionUnixProcessID 方法查询 PID + QDBusReply reply = dbusInterface.call("GetConnectionUnixProcessID", caller); + if (reply.isValid()) { + quint32 pid = reply.value(); + qWarning() << "Caller Pid :" << pid; + + getPathByPid(pid); + getPPidByPid(pid); + } else { + qWarning() << "Get caller pid failed :" << reply.error().message(); + } + } + } +} + +bool DBusShutdownAgent::Visible() const +{ + return m_model->visible() && (m_model->currentModeState() == SessionBaseModel::ModeStatus::PowerMode || m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode); } diff --git a/src/dde-lock/dbus/dbusshutdownagent.h b/src/dde-lock/dbus/dbusshutdownagent.h index 46fc5098..06f9d78a 100644 --- a/src/dde-lock/dbus/dbusshutdownagent.h +++ b/src/dde-lock/dbus/dbusshutdownagent.h @@ -1,31 +1,15 @@ -/* - * Copyright (C) 2011 ~ 2020 Uniontech Technology Co., Ltd. - * - * Author: chenjun - * - * Maintainer: chenjun - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSSHUTDOWNAGENT_H #define DBUSSHUTDOWNAGENT_H #include +#include class SessionBaseModel; -class DBusShutdownAgent : public QObject +class DBusShutdownAgent : public QObject, protected QDBusContext { Q_OBJECT public: @@ -39,9 +23,17 @@ class DBusShutdownAgent : public QObject void Hibernate(); void SwitchUser(); void Lock(); + void UpdateAndShutdown(); + void UpdateAndReboot(); + bool Visible() const; private: - bool canShowShutDown(); + bool canShowShutDown() const; + bool isUpdating() const; + + void getPathByPid(quint32 pid); + void getPPidByPid(quint32 pid); + void getCallerBySender(); private: SessionBaseModel *m_model; diff --git a/src/dde-lock/dbus/dbusshutdownfrontservice.cpp b/src/dde-lock/dbus/dbusshutdownfrontservice.cpp index 0e0b20b3..a607798d 100644 --- a/src/dde-lock/dbus/dbusshutdownfrontservice.cpp +++ b/src/dde-lock/dbus/dbusshutdownfrontservice.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2020 Uniontech Technology Co., Ltd. - * - * Author: chenjun - * - * Maintainer: chenjun - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbusshutdownfrontservice.h" @@ -42,11 +25,21 @@ void DBusShutdownFrontService::Shutdown() parent()->Shutdown(); } +void DBusShutdownFrontService::UpdateAndShutdown() +{ + parent()->UpdateAndShutdown(); +} + void DBusShutdownFrontService::Restart() { parent()->Restart(); } +void DBusShutdownFrontService::UpdateAndReboot() +{ + parent()->UpdateAndReboot(); +} + void DBusShutdownFrontService::Logout() { parent()->Logout(); @@ -71,3 +64,8 @@ void DBusShutdownFrontService::Lock() { parent()->Lock(); } + +bool DBusShutdownFrontService::visible() const +{ + return parent()->Visible(); +} diff --git a/src/dde-lock/dbus/dbusshutdownfrontservice.h b/src/dde-lock/dbus/dbusshutdownfrontservice.h index f8983806..812033b4 100644 --- a/src/dde-lock/dbus/dbusshutdownfrontservice.h +++ b/src/dde-lock/dbus/dbusshutdownfrontservice.h @@ -1,38 +1,19 @@ -/* - * Copyright (C) 2011 ~ 2020 Uniontech Technology Co., Ltd. - * - * Author: chenjun - * - * Maintainer: chenjun - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSSHUTDOWNFRONTSERVICE_H #define DBUSSHUTDOWNFRONTSERVICE_H #include "dbusshutdownagent.h" + #include -#include -#include QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; -class QStringList; class QVariant; QT_END_NAMESPACE @@ -42,7 +23,11 @@ QT_END_NAMESPACE class DBusShutdownFrontService : public QDBusAbstractAdaptor { Q_OBJECT +#ifndef ENABLE_DSS_SNIPE Q_CLASSINFO("D-Bus Interface", "com.deepin.dde.shutdownFront") +#else + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.ShutdownFront1") +#endif public: explicit DBusShutdownFrontService(DBusShutdownAgent *parent); @@ -51,6 +36,11 @@ class DBusShutdownFrontService : public QDBusAbstractAdaptor { inline DBusShutdownAgent *parent() const { return static_cast(QObject::parent()); } +public: // PROPERTIES + Q_PROPERTY(bool Visible READ visible) + + bool visible() const; + public Q_SLOTS: void Show(); void Shutdown(); @@ -60,9 +50,12 @@ public Q_SLOTS: void Hibernate(); void SwitchUser(); void Lock(); + void UpdateAndShutdown(); + void UpdateAndReboot(); Q_SIGNALS: void ChangKey(QString key); + void Visible(bool visible); }; #endif // DBUSSHUTDOWNFRONTSERVICE_H diff --git a/src/dde-lock/lockframe.cpp b/src/dde-lock/lockframe.cpp index 59904761..55dc7274 100644 --- a/src/dde-lock/lockframe.cpp +++ b/src/dde-lock/lockframe.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "lockframe.h" @@ -30,15 +9,22 @@ #include "userinfo.h" #include "warningcontent.h" #include "public_func.h" +#include "dconfig_helper.h" -#include +#include #include #include + +#include "dbusconstant.h" +#ifndef ENABLE_DSS_SNIPE #include -#include -#include #include +#else +#include +#endif + +#define LOCK_START_EFFECT 16 //锁屏动效比较特殊,窗管根据这个动效值进行处理 xcb_atom_t internAtom(xcb_connection_t *connection, const char *name, bool only_if_exists) { @@ -58,94 +44,78 @@ xcb_atom_t internAtom(xcb_connection_t *connection, const char *name, bool only_ } LockFrame::LockFrame(SessionBaseModel *const model, QWidget *parent) - : FullscreenBackground(model, parent) + : FullScreenBackground(model, parent) , m_model(model) - , m_lockContent(new LockContent(model)) - , m_warningContent(nullptr) , m_enablePowerOffKey(false) , m_autoExitTimer(nullptr) { +#ifndef ENABLE_DSS_SNIPE xcb_connection_t *connection = QX11Info::connection(); +#else + xcb_connection_t *connection = qGuiApp->nativeInterface()->connection(); +#endif if (connection) { xcb_atom_t cook = internAtom(connection, "_DEEPIN_LOCK_SCREEN", false); xcb_change_property(connection, XCB_PROP_MODE_REPLACE, static_cast(winId()), cook, XCB_ATOM_ATOM, 32, 1, &cook); - } - updateBackground(m_model->currentUser()->greeterBackground()); + // x11下通过窗口属性设置锁屏启动动效 + xcb_atom_t startup = internAtom(connection, "_DEEPIN_NET_STARTUP", false); + quint32 value = LOCK_START_EFFECT; + xcb_change_property(connection, XCB_PROP_MODE_REPLACE, static_cast(winId()), + startup, XCB_ATOM_CARDINAL, 32, 1, &value); + } setAccessibleName("LockFrame"); - m_lockContent->setAccessibleName("LockContent"); - m_lockContent->hide(); - setContent(m_lockContent); - - connect(m_lockContent, &LockContent::requestSwitchToUser, this, &LockFrame::requestSwitchToUser); - connect(m_lockContent, &LockContent::requestSetLayout, this, &LockFrame::requestSetLayout); - connect(m_lockContent, &LockContent::requestBackground, this, static_cast(&LockFrame::updateBackground)); - connect(m_lockContent, &LockContent::requestStartAuthentication, this, &LockFrame::requestStartAuthentication); - connect(m_lockContent, &LockContent::sendTokenToAuth, this, &LockFrame::sendTokenToAuth); - connect(m_lockContent, &LockContent::requestEndAuthentication, this, &LockFrame::requestEndAuthentication); - connect(m_lockContent, &LockContent::requestLockFrameHide, this, &LockFrame::hide); - connect(m_lockContent, &LockContent::authFinished, this, [this] { - hide(); - emit requestEnableHotzone(true); - emit authFinished(); - }); - connect(model, &SessionBaseModel::showUserList, this, &LockFrame::showUserList); - connect(model, &SessionBaseModel::showLockScreen, this, &LockFrame::showLockScreen); - connect(model, &SessionBaseModel::showShutdown, this, &LockFrame::showShutdown); - connect(model, &SessionBaseModel::shutdownInhibit, this, &LockFrame::shutdownInhibit); - connect(model, &SessionBaseModel::cancelShutdownInhibit, this, &LockFrame::cancelShutdownInhibit); - connect(model, &SessionBaseModel::prepareForSleep, this, [ = ](bool isSleep) { - //不管是待机还是唤醒均不响应电源按键信号 - m_enablePowerOffKey = false; - - //唤醒1秒后才响应电源按键信号,避免待机唤醒时响应信号,将界面切换到关机选项 - if (!isSleep) { - QTimer::singleShot(1000, this, [ = ] { - m_enablePowerOffKey = true; - }); - } - //待机时由锁屏提供假黑屏,唤醒时显示正常界面 - model->setIsBlackMode(isSleep); - model->setVisible(true); - - if (!isSleep) { - //待机唤醒后检查是否需要密码,若不需要密码直接隐藏锁定界面 - if (QGSettings::isSchemaInstalled("com.deepin.dde.power")) { - QGSettings powerSettings("com.deepin.dde.power", QByteArray(), this); - if (!powerSettings.get("sleep-lock").toBool()) { - hide(); - } - } - } - } ); + // wayland下通过DTK设置锁屏启动动效 + if (qgetenv("XDG_SESSION_TYPE").contains("wayland")) { + DPlatformWindowHandle handle(this, this); + handle.setWindowStartUpEffect(static_cast(LOCK_START_EFFECT)); + } + if (!currentContent) { + setContent(LockContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::LockContent); + } + connect(LockContent::instance(), &LockContent::requestBackground, this, static_cast(&LockFrame::updateBackground)); + connect(model, &SessionBaseModel::prepareForSleep, this, &LockFrame::prepareForSleep); connect(model, &SessionBaseModel::authFinished, this, [this](bool success) { if (success) { Q_EMIT requestEnableHotzone(true); - hide(); + if (!WarningContent::instance()->supportDelayOrWait()) + m_model->setVisible(false); } }); //程序启动1秒后才响应电源按键信号,避免第一次待机唤醒启动锁屏程序后响应信号,将界面切换到关机选项 - QTimer::singleShot(1000, this, [ = ] { + QTimer::singleShot(1000, this, [this] { m_enablePowerOffKey = true; }); - if (getDConfigValue(getDefaultConfigFileName(), "autoExit", false).toBool()) { + if (DConfigHelper::instance()->getConfig("autoExit", false).toBool()) { m_autoExitTimer = new QTimer(this); - m_autoExitTimer->setInterval(1000*60); //1分钟 + m_autoExitTimer->setInterval(1000 * 60); //1分钟 m_autoExitTimer->setSingleShot(true); connect(m_autoExitTimer, &QTimer::timeout, qApp, &QApplication::quit); } } +LockFrame::~LockFrame() +{ + if (LockContent::instance()->parent() == this) { + LockContent::instance()->setParent(nullptr); + } + + if (WarningContent::instance()->parent() == this) { + WarningContent::instance()->setParent(nullptr); + } +} + bool LockFrame::event(QEvent *event) { if (event->type() == QEvent::KeyRelease) { - QString keyValue = ""; + QString keyValue = ""; switch (static_cast(event)->key()) { case Qt::Key_PowerOff: { if (!handlePoweroffKey()) { @@ -193,26 +163,45 @@ bool LockFrame::event(QEvent *event) keyValue = "mon-brightness-down"; break; } + // 锁屏时会独占键盘,需要单独处理F1待机事件 + case Qt::Key_Sleep: { + m_model->setPowerAction(SessionBaseModel::RequireSuspend); + break; + } } if (keyValue != "") { +#ifdef ENABLE_DSS_SNIPE + // v25 dde-daemon接受小驼峰命名的name + emit sendKeyValue(qtifyName(keyValue)); +#else emit sendKeyValue(keyValue); +#endif } } - return FullscreenBackground::event(event); + return FullScreenBackground::event(event); } void LockFrame::resizeEvent(QResizeEvent *event) { - m_lockContent->resize(size()); - FullscreenBackground::resizeEvent(event); + if (contentVisible()) { + LockContent::instance()->resize(size()); + } + FullScreenBackground::resizeEvent(event); } bool LockFrame::handlePoweroffKey() { - QDBusInterface powerInter("com.deepin.daemon.Power","/com/deepin/daemon/Power","com.deepin.daemon.Power"); + qCInfo(DDE_SHELL) << "Handle poweroff key"; + // 升级的时候,不响应电源按钮 + if (m_model->currentContentType() == SessionBaseModel::UpdateContent) { + qCInfo(DDE_SHELL) << "Is updating, do not handle power off key"; + return false; + } + + QDBusInterface powerInter(DSS_DBUS::sessionPowerService, DSS_DBUS::sessionPowerPath,DSS_DBUS::sessionPowerService); if (!powerInter.isValid()) { - qDebug() << "powerInter is not valid"; + qCWarning(DDE_SHELL) << "Poweroff interface is not valid"; return false; } bool isBattery = powerInter.property("OnBattery").toBool(); @@ -222,11 +211,14 @@ bool LockFrame::handlePoweroffKey() } else { action = powerInter.property("LinePowerPressPowerBtnAction").toInt(); } - qDebug() << "battery is: " << isBattery << "," << action; + qCDebug(DDE_SHELL) << "Whether on battery: " << isBattery << ", press poweroff button action: " << action; // 需要特殊处理:关机(0)和无任何操作(4) if (action == 0) { - //锁屏时或显示关机界面时,需要确认是否关机 - emit m_model->onRequirePowerAction(SessionBaseModel::PowerAction::RequireShutdown, false); + // 待机刚唤醒一段时间内不响应电源按键事件 + if (m_enablePowerOffKey) { + //锁屏时或显示关机界面时,需要确认是否关机 + emit m_model->onRequirePowerAction(SessionBaseModel::PowerAction::RequireShutdown, false); + } return true; } else if (action == 4) { // 先检查当前是否允许响应电源按键 @@ -239,76 +231,13 @@ bool LockFrame::handlePoweroffKey() return false; } -void LockFrame::showUserList() -{ - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); - QTimer::singleShot(10, this, [ = ] { - this->show(); - }); -} - -void LockFrame::showLockScreen() -{ - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); - show(); -} - -void LockFrame::showShutdown() -{ - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); - show(); -} - -void LockFrame::shutdownInhibit(const SessionBaseModel::PowerAction action, bool needConfirm) -{ - //如果其他显示屏界面已经检查过是否允许关机,此显示屏上的界面不再显示,避免重复检查并触发信号 - if (m_model->isCheckedInhibit()) return; - //记录多屏状态下当前显示屏是否显示内容 - bool old_visible = contentVisible(); - - if (!m_warningContent) { - m_warningContent = new WarningContent(m_model, action, this); - m_warningContent->setAccessibleName("WarningContent"); - } else { - m_warningContent->setPowerAction(action); - } - m_warningContent->resize(size()); - setContent(m_warningContent); - - //多屏状态下,当前界面显示内容时才显示提示界面 - if (old_visible) { - setContentVisible(true); - m_lockContent->hide(); - } - - //检查是否允许关机 - m_warningContent->beforeInvokeAction(needConfirm); -} - -void LockFrame::cancelShutdownInhibit() -{ - //允许关机检查结束后切换界面 - //记录多屏状态下当前显示屏是否显示内容 - bool old_visible = contentVisible(); - - setContent(m_lockContent); - - //隐藏提示界面 - if (m_warningContent) { - m_warningContent->hide(); - } - - //多屏状态下,当前界面显示内容时才显示 - if (old_visible) { - setContentVisible(true); - } -} - void LockFrame::keyPressEvent(QKeyEvent *e) { switch (e->key()) { #ifdef QT_DEBUG - case Qt::Key_Escape: qApp->quit(); break; + case Qt::Key_Escape: + qApp->quit(); + break; #endif } } @@ -317,20 +246,32 @@ void LockFrame::showEvent(QShowEvent *event) { emit requestEnableHotzone(false); - m_model->setVisible(true); if (m_autoExitTimer) m_autoExitTimer->stop(); - return FullscreenBackground::showEvent(event); + return FullScreenBackground::showEvent(event); } void LockFrame::hideEvent(QHideEvent *event) { emit requestEnableHotzone(true); - m_model->setVisible(false); if (m_autoExitTimer) m_autoExitTimer->start(); - return FullscreenBackground::hideEvent(event); + return FullScreenBackground::hideEvent(event); +} + +void LockFrame::prepareForSleep(bool isSleep) +{ + //不管是待机还是唤醒均不响应电源按键信号 + m_enablePowerOffKey = false; + // 唤醒不需要密码时,在性能差的机器上可能会在1秒后才收到电源事件,依就会响应电源事件 + // 或者将延时改的更长 + //唤醒时间改为3秒后才响应电源按键信号,避免待机唤醒时响应信号,将界面切换到关机选项 + if (!isSleep) { + QTimer::singleShot(3000, this, [this] { + m_enablePowerOffKey = true; + }); + } } diff --git a/src/dde-lock/lockframe.h b/src/dde-lock/lockframe.h index 79ec1290..a52c61f6 100644 --- a/src/dde-lock/lockframe.h +++ b/src/dde-lock/lockframe.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOCKFRAME #define LOCKFRAME @@ -30,27 +9,19 @@ #include "sessionbasemodel.h" #include -#include -#include -#include #include -const QString DBUS_LOCK_PATH = "/com/deepin/dde/lockFront"; -const QString DBUS_LOCK_NAME = "com.deepin.dde.lockFront"; - -const QString DBUS_SHUTDOWN_PATH = "/com/deepin/dde/shutdownFront"; -const QString DBUS_SHUTDOWN_NAME = "com.deepin.dde.shutdownFront"; - class DBusLockService; class LockContent; class WarningContent; class User; -class LockFrame: public FullscreenBackground +class LockFrame: public FullScreenBackground { Q_OBJECT public: - LockFrame(SessionBaseModel *const model, QWidget *parent = nullptr); + explicit LockFrame(SessionBaseModel *const model, QWidget *parent = nullptr); + ~LockFrame(); signals: void requestSwitchToUser(std::shared_ptr user); @@ -59,16 +30,11 @@ class LockFrame: public FullscreenBackground void sendKeyValue(QString keyValue); void requestStartAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); + void sendTokenToAuth(const QString &account, const AuthType authType, const QString &token); void requestEndAuthentication(const QString &account, const int authType); - void authFinished(); -public slots: - void showUserList(); - void showLockScreen(); - void showShutdown(); - void shutdownInhibit(const SessionBaseModel::PowerAction action, bool needConfirm); - void cancelShutdownInhibit(); +private slots: + void prepareForSleep(bool isSleep); protected: void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; @@ -82,8 +48,6 @@ public slots: private: SessionBaseModel *m_model; - LockContent *m_lockContent; - WarningContent *m_warningContent; bool m_enablePowerOffKey; QTimer *m_autoExitTimer; }; diff --git a/src/dde-lock/lockworker.cpp b/src/dde-lock/lockworker.cpp index aab37393..1c034509 100644 --- a/src/dde-lock/lockworker.cpp +++ b/src/dde-lock/lockworker.cpp @@ -1,21 +1,31 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "lockworker.h" #include "authcommon.h" #include "sessionbasemodel.h" #include "userinfo.h" +#include "login_plugin_util.h" +#include "public_func.h" +#include "dconfig_helper.h" +#include "warningcontent.h" +#include "fullscreenbackground.h" +#include "updateworker.h" +#include "lockcontent.h" +#include "signal_bridge.h" +#include "mfasequencecontrol.h" #include -#include -#include #include -#include -#include #include -#include #include +#include "dbusconstant.h" + #define DOMAIN_BASE_UID 10000 using namespace Auth; @@ -27,11 +37,12 @@ LockWorker::LockWorker(SessionBaseModel *const model, QObject *parent) , m_authenticating(false) , m_isThumbAuth(false) , m_authFramework(new DeepinAuthFramework(this)) - , m_lockInter(new DBusLockService("com.deepin.dde.LockService", "/com/deepin/dde/LockService", QDBusConnection::systemBus(), this)) - , m_hotZoneInter(new DBusHotzone("com.deepin.daemon.Zone", "/com/deepin/daemon/Zone", QDBusConnection::sessionBus(), this)) + , m_lockInter(new DBusLockService(DSS_DBUS::lockService, DSS_DBUS::lockServicePath, QDBusConnection::systemBus(), this)) + , m_hotZoneInter(new DBusHotzone(DSS_DBUS::zoneService, DSS_DBUS::zonePath, QDBusConnection::sessionBus(), this)) , m_resetSessionTimer(new QTimer(this)) , m_limitsUpdateTimer(new QTimer(this)) - , m_sessionManagerInter(new SessionManagerInter("com.deepin.SessionManager", "/com/deepin/SessionManager", QDBusConnection::sessionBus(), this)) + , m_wakeUpAuthTimer(new QTimer(this)) + , m_sessionManagerInter(new SessionManagerInter(DSS_DBUS::sessionManagerService, DSS_DBUS::sessionManagerPath, QDBusConnection::sessionBus(), this)) , m_switchosInterface(new HuaWeiSwitchOSInterface("com.huawei", "/com/huawei/switchos", QDBusConnection::sessionBus(), this)) , m_kglobalaccelInter(nullptr) , m_kwinInter(nullptr) @@ -45,19 +56,35 @@ LockWorker::LockWorker(SessionBaseModel *const model, QObject *parent) m_resetSessionTimer->setInterval(15000); - if (QGSettings::isSchemaInstalled("com.deepin.dde.session-shell")) { - m_gsettings = new QGSettings("com.deepin.dde.session-shell", "/com/deepin/dde/session-shell/", this); - if(m_gsettings->keys().contains("authResetTime")){ - int resetTime = m_gsettings->get("auth-reset-time").toInt(); - if(resetTime > 0) - m_resetSessionTimer->setInterval(resetTime); - } + // On standby resume, ActiveChanged and PrepareForSleep are reported back to back; + // the 300ms single-shot timer coalesces signal-triggered authentication requests + // that occur within 300ms. + m_wakeUpAuthTimer->setSingleShot(true); + m_wakeUpAuthTimer->setInterval(300); + connect(m_wakeUpAuthTimer, &QTimer::timeout, this, [this](){ + createAuthentication(m_model->currentUser()->name()); + }); + +#ifndef ENABLE_DSS_SNIPE + if (m_gsettings != nullptr && m_gsettings->keys().contains("authResetTime")){ + int resetTime = m_gsettings->get("auth-reset-time").toInt(); + if(resetTime > 0) + m_resetSessionTimer->setInterval(resetTime); + } +#else + if (!m_dConfig) { + m_dConfig = DConfig::create("org.deepin.dde.session-shell", "org.deepin.dde.session-shell", QString(), this); } + int resetTime = m_dConfig->value("authResetTime", 15000).toInt(); + if (resetTime > 0) { + m_resetSessionTimer->setInterval(resetTime); + } +#endif m_resetSessionTimer->setSingleShot(true); - connect(m_resetSessionTimer, &QTimer::timeout, this, [=] { + connect(m_resetSessionTimer, &QTimer::timeout, this, [this] { endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + destroyAuthentication(m_account); createAuthentication(m_account); }); } @@ -70,22 +97,27 @@ void LockWorker::initConnections() /* com.deepin.daemon.Accounts */ connect(m_accountsInter, &AccountsInter::UserAdded, m_model, static_cast(&SessionBaseModel::addUser)); connect(m_accountsInter, &AccountsInter::UserDeleted, m_model, static_cast(&SessionBaseModel::removeUser)); - // connect(m_accountsInter, &AccountsInter::UserListChanged, m_model, &SessionBaseModel::updateUserList); // UserListChanged信号的处理, 改用UserAdded和UserDeleted信号替代 connect(m_accountsInter, &AccountsInter::UserDeleted, this, [this](const QString &path) { if (path == m_model->currentUser()->path()) { m_model->updateCurrentUser(m_lockInter->CurrentUser()); } }); - connect(m_loginedInter, &LoginedInter::LastLogoutUserChanged, m_model, static_cast(&SessionBaseModel::updateLastLogoutUser)); connect(m_loginedInter, &LoginedInter::UserListChanged, m_model, &SessionBaseModel::updateLoginedUserList); /* com.deepin.daemon.Authenticate */ connect(m_authFramework, &DeepinAuthFramework::FramworkStateChanged, m_model, &SessionBaseModel::updateFrameworkState); connect(m_authFramework, &DeepinAuthFramework::LimitsInfoChanged, this, [this](const QString &account) { - qDebug() << "DeepinAuthFramework::LimitsInfoChanged:" << account; if (account == m_model->currentUser()->name()) { m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(account)); } }); + connect(m_authFramework, &DeepinAuthFramework::DeviceChanged, this, [this](const int type, const int state) { + // 如果是单因或者多因且包含该类型认证,需要重新创建认证 + if (m_model->visible() && (!m_model->getAuthProperty().MFAFlag || (m_model->getAuthProperty().MFAFlag && (m_model->getAuthProperty().AuthType & type)))) { + endAuthentication(m_account, AT_All); + destroyAuthentication(m_account); + createAuthentication(m_account); + } + }); connect(m_authFramework, &DeepinAuthFramework::SupportedEncryptsChanged, m_model, &SessionBaseModel::updateSupportedEncryptionType); connect(m_authFramework, &DeepinAuthFramework::SupportedMixAuthFlagsChanged, m_model, &SessionBaseModel::updateSupportedMixAuthFlags); /* com.deepin.daemon.Authenticate.Session */ @@ -96,52 +128,124 @@ void LockWorker::initConnections() connect(m_authFramework, &DeepinAuthFramework::AuthStateChanged, this, &LockWorker::onAuthStateChanged); connect(m_authFramework, &DeepinAuthFramework::FactorsInfoChanged, m_model, &SessionBaseModel::updateFactorsInfo); /* com.deepin.dde.LockService */ - connect(m_lockInter, &DBusLockService::UserChanged, this, [=](const QString &json) { - qInfo() << "DBusLockService::UserChanged:" << json; - QTimer::singleShot(100, this, [ = ] { + connect(m_lockInter, &DBusLockService::UserChanged, this, [this](const QString &json) { + qCInfo(DDE_SHELL) << "DBus lock service user changed, user: " << json; + QTimer::singleShot(100, this, [this] { + if(m_model->currentContentType() == SessionBaseModel::UpdateContent){ + qCInfo(DDE_SHELL) << "Is updating, do not answer user changed signal"; + return; + } + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); }); m_resetSessionTimer->stop(); }); connect(m_lockInter, &DBusLockService::Event, this, &LockWorker::lockServiceEvent); /* com.deepin.SessionManager */ - connect(m_sessionManagerInter, &SessionManagerInter::Unlock, this, [=] { + connect(m_sessionManagerInter, &SessionManagerInter::Unlock, this, [this] { m_authenticating = false; m_password.clear(); emit m_model->authFinished(true); }); + /* org.freedesktop.login1.Session */ - connect(m_login1SessionSelf, &Login1SessionSelf::ActiveChanged, this, [=](bool active) { - qInfo() << "DBusLockService::ActiveChanged:" << active; - if (active) { - createAuthentication(m_model->currentUser()->name()); + connect(m_login1SessionSelf, &Login1SessionSelf::ActiveChanged, this, [this](bool active) { + qCInfo(DDE_SHELL) << "DBus lock service active changed, active: " << active << ", model visible: " << m_model->visible(); + if (m_model->currentContentType() == SessionBaseModel::UpdateContent) { + qCInfo(DDE_SHELL) << "Updating, do not answer login1 session self `ActiveChanged` signal"; + return; + } + + if (active && m_model->visible()) { + m_wakeUpAuthTimer->start(); } else { + m_wakeUpAuthTimer->stop(); endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + destroyAuthentication(m_account); + } + +#ifdef ENABLE_DSS_SNIPE + if (active && !m_model->visible()) { + m_model->showLockScreen(); + } +#endif + }); + + // 在待机时启动定时器,如果定时器超时的时间离待机时间大于15秒,则认为已经唤醒,停止定时器,并设置黑屏模式为false + // prepareForSleep信号有时候会会延迟,所以需要定时器来确认是否已经唤醒,尽早显示出锁屏。 + static QDateTime doSuspendTime = QDateTime::currentDateTime(); + auto checkSystemWakeupTimer = new QTimer(this); + checkSystemWakeupTimer->setInterval(500); + connect(checkSystemWakeupTimer, &QTimer::timeout, this, [this, checkSystemWakeupTimer] { + const int secs = static_cast(doSuspendTime.secsTo(QDateTime::currentDateTime())); + if (secs >= 15) { // 小风险:如果15秒还没有待机下去,那就把锁屏显示出来了,不过15秒没有待机的才是大问题 + qCInfo(DDE_SHELL) << "System wakeup,hide black widget"; + checkSystemWakeupTimer->stop(); + m_model->setIsBlackMode(false); } }); /* org.freedesktop.login1.Manager */ - connect(m_login1Inter, &DBusLogin1Manager::PrepareForSleep, this, [=](bool isSleep) { - qInfo() << "DBusLogin1Manager::PrepareForSleep:" << isSleep; + connect(m_login1Inter, &DBusLogin1Manager::PrepareForSleep, this, [this, checkSystemWakeupTimer](bool isSleep) { + qCInfo(DDE_SHELL) << "DBus login1 manager prepare for sleep: " << isSleep; + if (m_model->currentContentType() == SessionBaseModel::UpdateContent) { + qCInfo(DDE_SHELL) << "Updating, do not answer `PrepareForSleep` signal"; + return; + } + +#ifndef ENABLE_DSS_SNIPE + const bool sleepLock = m_model->getPowerGSettings("", "sleepLock").toBool(); +#else + const bool sleepLock = isSleepLock(); +#endif + qCInfo(DDE_SHELL) << "Lock screen when system wakes up: " << sleepLock << ", is visible:" << m_model->visible(); + + FullScreenBackground::setContent(LockContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::LockContent); + if (isSleep) { - endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + checkSystemWakeupTimer->start(); + m_wakeUpAuthTimer->stop(); + doSuspendTime = QDateTime::currentDateTime(); + m_model->setIsBlackMode(true); + // 休眠时按需拉起锁屏,注意此时是被动响应休眠 + if (sleepLock && m_login1SessionSelf->active()) { + // 仅sleepLock配置开启时执行 + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + setLocked(true); + m_model->setVisible(true); + + qCInfo(DDE_SHELL) << "locked for sleepLock config"; + } } else { - createAuthentication(m_model->currentUser()->name()); + SessionBaseModel::ModeStatus status = m_model->currentModeState(); + if (isLocked() || (m_model->isNoPasswordLogin() && (status == SessionBaseModel::ModeStatus::PowerMode || status == SessionBaseModel::ModeStatus::PasswordMode))) { + // 唤醒时如果处于lock状态,重置认证 + if (m_login1SessionSelf->active()) { + endAuthentication(m_account, AT_All); + destroyAuthentication(m_account); + m_wakeUpAuthTimer->start(); + } + } else { + // 处理其他流程设置的可见状态 + m_model->setVisible(false); + m_wakeUpAuthTimer->stop(); + } + // 避免在电源选项处理中设置密码模式,会导致唤醒后闪锁屏 + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + m_model->setIsBlackMode(false); } emit m_model->prepareForSleep(isSleep); }); /* model */ - connect(m_model, &SessionBaseModel::authTypeChanged, this, [=](const int type) { - qInfo() << "Auth type changed: " << type; + connect(m_model, &SessionBaseModel::authTypeChanged, this, [this](const AuthFlags type) { + qCInfo(DDE_SHELL) << "Auth type changed: " << type; if (type > 0 && m_model->getAuthProperty().MFAFlag) { startAuthentication(m_account, type); } - // OPTMIZE: 为什么要特意用一个timer延时? m_limitsUpdateTimer->start(); }); connect(m_model, &SessionBaseModel::onPowerActionChanged, this, &LockWorker::doPowerAction); - connect(m_model, &SessionBaseModel::visibleChanged, this, [=](bool visible) { + connect(m_model, &SessionBaseModel::visibleChanged, this, [this](bool visible) { if (visible) { if (m_model->currentModeState() != SessionBaseModel::ShutDownMode && m_model->currentModeState() != SessionBaseModel::UserMode) { createAuthentication(m_model->currentUser()->name()); @@ -149,11 +253,12 @@ void LockWorker::initConnections() } else { m_resetSessionTimer->stop(); endAuthentication(m_account, AT_All); - destoryAuthentication(m_model->currentUser()->name()); + destroyAuthentication(m_model->currentUser()->name()); setCurrentUser(m_model->currentUser()); + setLocked(false); } }); - connect(m_model, &SessionBaseModel::onStatusChanged, this, [=](SessionBaseModel::ModeStatus state) { + connect(m_model, &SessionBaseModel::onStatusChanged, this, [this](SessionBaseModel::ModeStatus state) { if (state == SessionBaseModel::ModeStatus::PowerMode || state == SessionBaseModel::ModeStatus::ShutDownMode) { checkPowerInfo(); } @@ -163,58 +268,90 @@ void LockWorker::initConnections() if (m_authFramework->isDeepinAuthValid()) m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_account)); }); - connect(m_dbusInter, &DBusObjectInter::NameOwnerChanged, this, [=](const QString &name, const QString &oldOwner, const QString &newOwner) { - Q_UNUSED(oldOwner) - if (name == "com.deepin.daemon.Authenticate" && newOwner != "" && m_model->visible() && m_sessionManagerInter->locked()) { + connect(m_dbusInter, &DBusObjectInter::NameOwnerChanged, this, [this](const QString &name, const QString &oldOwner, const QString &newOwner) { + //该dbus监听主要处理DA升级使用,如果oldOwner为空,说明是第一次使用,不需要重新开启认证 + if (oldOwner == "") + return; + + if (name == DSS_DBUS::authenticateService && newOwner != "" && m_model->visible() && m_sessionManagerInter->locked()) { m_resetSessionTimer->stop(); endAuthentication(m_account, AT_All); createAuthentication(m_model->currentUser()->name()); } }); - connect(m_model, &SessionBaseModel::activeAuthChanged, this, [this] (const bool active) { - if (!active || m_model->currentModeState() == SessionBaseModel::ModeStatus::PasswordMode) + connect(m_model, &SessionBaseModel::activeAuthChanged, this, [this](const bool active) { + const auto currentMode = m_model->currentModeState(); + const auto currenContent = m_model->currentContentType(); + qCInfo(DDE_SHELL) << "Active auth changed, active: " << active + << ", current mode: " << currentMode + << ", currenContent: " << currenContent; + + if (!active || currentMode == SessionBaseModel::PasswordMode || currenContent == SessionBaseModel::UpdateContent) { + qCInfo(DDE_SHELL) << "Do not response active auth changed signal"; return; + } createAuthentication(m_model->currentUser()->name()); - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + m_model->setCurrentModeState(SessionBaseModel::PasswordMode); + }); + + connect(UpdateWorker::instance(), &UpdateWorker::requestExitUpdating, this, [this] { + m_model->setVisible(false); + m_model->setUpdatePowerMode(SessionBaseModel::UPM_None); + m_model->setCurrentModeState(SessionBaseModel::PasswordMode); + FullScreenBackground::setContent(LockContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::LockContent); }); + connect(&SignalBridge::ref(), &SignalBridge::requestSendExtraInfo, this, &LockWorker::sendExtraInfo); } void LockWorker::initData() { - /* com.deepin.daemon.Accounts */ - m_model->updateUserList(m_accountsInter->userList()); - m_model->updateLastLogoutUser(m_loginedInter->lastLogoutUser()); - m_model->updateLoginedUserList(m_loginedInter->userList()); + auto list = m_accountsInter->userList(); + if (!list.isEmpty()) { + /* com.deepin.daemon.Accounts */ + m_model->updateUserList(m_accountsInter->userList()); + m_model->updateLoginedUserList(m_loginedInter->userList()); - /* com.deepin.udcp.iam */ - QDBusInterface ifc("com.deepin.udcp.iam", "/com/deepin/udcp/iam", "com.deepin.udcp.iam", QDBusConnection::systemBus(), this); - const bool allowShowCustomUser = valueByQSettings("", "loginPromptInput", false) || ifc.property("Enable").toBool(); - m_model->setAllowShowCustomUser(allowShowCustomUser); + m_model->setUserlistVisible(valueByQSettings("", "userlist", true)); + /* com.deepin.udcp.iam */ + QDBusInterface ifc(DSS_DBUS::udcpIamService, DSS_DBUS::udcpIamPath, DSS_DBUS::udcpIamService, QDBusConnection::systemBus(), this); + const bool allowShowCustomUser = (!m_model->userlistVisible()) || valueByQSettings("", "loginPromptInput", false) || + ifc.property("Enable").toBool() || checkIsADDomain(); + m_model->setAllowShowCustomUser(allowShowCustomUser); - /* init server user or custom user */ - if (DSysInfo::deepinType() == DSysInfo::DeepinServer || m_model->allowShowCustomUser()) { - std::shared_ptr user(new User()); - m_model->setIsServerModel(DSysInfo::deepinType() == DSysInfo::DeepinServer); - m_model->addUser(user); - } + /* init server user or custom user */ + if (DSysInfo::deepinType() == DSysInfo::DeepinServer || m_model->allowShowCustomUser()) { + std::shared_ptr user(new User()); + m_model->setIsServerModel(DSysInfo::deepinType() == DSysInfo::DeepinServer); + m_model->addUser(user); + } - /* com.deepin.dde.LockService */ - std::shared_ptr user_ptr = m_model->findUserByUid(getuid()); - if (user_ptr.get()) { - m_model->updateCurrentUser(user_ptr); - const QString &userJson = m_lockInter->CurrentUser(); - QJsonParseError jsonParseError; - const QJsonDocument userDoc = QJsonDocument::fromJson(userJson.toUtf8(), &jsonParseError); - if (jsonParseError.error != QJsonParseError::NoError || userDoc.isEmpty()) { - qWarning() << "Failed to obtain current user information from LockService!"; + /* com.deepin.dde.LockService */ + std::shared_ptr user_ptr = m_model->findUserByUid(getuid()); + if (user_ptr.get()) { + m_model->updateCurrentUser(user_ptr); + const QString &userJson = m_lockInter->CurrentUser(); + QJsonParseError jsonParseError; + const QJsonDocument userDoc = QJsonDocument::fromJson(userJson.toUtf8(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || userDoc.isEmpty()) { + qCWarning(DDE_SHELL) << "Failed to obtain current user information from lock service!"; + } else { + const QJsonObject userObj = userDoc.object(); + m_model->currentUser()->setLastAuthType(AUTH_TYPE_CAST(userObj["AuthType"].toInt())); + m_model->currentUser()->setLastCustomAuth(userObj["LastCustomAuth"].toString()); + } } else { - const QJsonObject userObj = userDoc.object(); - m_model->currentUser()->setLastAuthType(userObj["AuthType"].toInt()); + m_model->updateCurrentUser(m_lockInter->CurrentUser()); } } else { - m_model->updateCurrentUser(m_lockInter->CurrentUser()); + qCWarning(DDE_SHELL) << "dbus com.deepin.daemon.Accounts userList is empty, use ..."; + + std::shared_ptr user(new User()); + m_model->addUser(user); + m_model->updateCurrentUser(user); + m_model->setAllowShowCustomUser(true); } /* com.deepin.daemon.Authenticate */ @@ -230,8 +367,15 @@ void LockWorker::initData() void LockWorker::initConfiguration() { +#ifndef ENABLE_DSS_SNIPE m_model->setAlwaysShowUserSwitchButton(getGSettings("", "switchuser").toInt() == AuthInterface::Always); m_model->setAllowShowUserSwitchButton(getGSettings("", "switchuser").toInt() == AuthInterface::Ondemand); +#else + m_model->setAlwaysShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Always); + m_model->setAllowShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Ondemand); +#endif + + m_model->setGsCheckpwd(isCheckPwdBeforeRebootOrShut()); checkPowerInfo(); } @@ -245,20 +389,22 @@ void LockWorker::initConfiguration() */ void LockWorker::onAuthStateChanged(const int type, const int state, const QString &message) { - qDebug() << "LockWorker::onAuthStateChanged:" << type << state << message; + qCInfo(DDE_SHELL) << "Auth type:" << type + << ", authentication state:" << state + << ", message:" << message; if (m_model->getAuthProperty().MFAFlag) { if (type == AT_All) { switch (state) { case AS_Success: - m_model->updateAuthState(type, state, message); - destoryAuthentication(m_account); + m_model->updateAuthState(AuthType(type), AuthState(state), message); + destroyAuthentication(m_account); onUnlockFinished(true); m_resetSessionTimer->stop(); break; case AS_Cancel: - m_model->updateAuthState(type, state, message); - destoryAuthentication(m_account); + m_model->updateAuthState(AuthType(type), AuthState(state), message); + destroyAuthentication(m_account); break; default: break; @@ -270,8 +416,13 @@ void LockWorker::onAuthStateChanged(const int type, const int state, const QStri && m_model->currentModeState() != SessionBaseModel::ModeStatus::ConfirmPasswordMode) { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } - m_resetSessionTimer->start(); - m_model->updateAuthState(type, state, message); + + // 处于序列化多因认证过程中时不要重置认证 + if (MFASequenceControl::instance().currentAuthType() == AuthType::AT_None) { + m_resetSessionTimer->start(); + } + + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; case AS_Failure: if (m_model->currentModeState() != SessionBaseModel::ModeStatus::PasswordMode @@ -279,15 +430,15 @@ void LockWorker::onAuthStateChanged(const int type, const int state, const QStri m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); if (!m_model->currentUser()->limitsInfo(type).locked && type != AT_Face && type != AT_Iris) { QTimer::singleShot(50, this, [this, type] { - startAuthentication(m_account, type); + startAuthentication(m_account, AuthType(type)); }); } QTimer::singleShot(50, this, [this, type, state, message] { - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); }); break; case AS_Locked: @@ -295,24 +446,24 @@ void LockWorker::onAuthStateChanged(const int type, const int state, const QStri && m_model->currentModeState() != SessionBaseModel::ModeStatus::ConfirmPasswordMode) { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); // TODO: 信号时序问题,考虑优化,Bug 89056 QTimer::singleShot(50, this, [this, type, state, message] { - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); }); break; case AS_Timeout: case AS_Error: - qWarning() << "Auth error, type: " << type << ", state: " << state << ", message: " << message; - endAuthentication(m_account, type); - m_model->updateAuthState(type, state, message); + qCWarning(DDE_SHELL) << "Auth error, type: " << type << ", state: " << state << ", message: " << message; + endAuthentication(m_account, AuthType(type)); + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; case AS_Unlocked: m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; default: - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; } } @@ -323,27 +474,37 @@ void LockWorker::onAuthStateChanged(const int type, const int state, const QStri m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); switch (state) { case AS_Success: - if ((type == AT_Face || type == AT_Iris) && m_model->visible()) - m_resetSessionTimer->start(); + if (m_model->currentUser()->isLdapUser() && type != AT_Custom && type != AT_All) { + auto loginType = LPUtil::loginType(); + if (loginType == LPUtil::Type::CLT_MFA) { + m_resetSessionTimer->setInterval(LPUtil::sessionTimeout()); + m_resetSessionTimer->start(); + break; + } + } + if (type == AT_Face || type == AT_Iris) { + m_resetSessionTimer->setInterval(DEFAULT_SESSION_TIMEOUT); + m_resetSessionTimer->start(); + } break; case AS_Failure: // 单因失败会返回明确的失败类型,不关注type为-1的情况 if (AT_All != type) { - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); // 人脸和虹膜需要手动重新开启验证 if (!m_model->currentUser()->limitsInfo(type).locked && type != AT_Face && type != AT_Iris) { QTimer::singleShot(50, this, [this, type] { - startAuthentication(m_account, type); + startAuthentication(m_account, AuthType(type)); }); } } break; case AS_Cancel: - destoryAuthentication(m_account); + destroyAuthentication(m_account); break; default: break; @@ -353,20 +514,38 @@ void LockWorker::onAuthStateChanged(const int type, const int state, const QStri void LockWorker::doPowerAction(const SessionBaseModel::PowerAction action) { +#ifndef ENABLE_DSS_SNIPE + bool sleepLock = m_model->getPowerGSettings("", "sleepLock").toBool(); +#else + bool sleepLock = isSleepLock(); +#endif + qCInfo(DDE_SHELL) << "Do power action:" << action; switch (action) { case SessionBaseModel::PowerAction::RequireSuspend: { m_model->setIsBlackMode(true); - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + int delayTime = 500; +#ifndef ENABLE_DSS_SNIPE if(m_gsettings && m_gsettings->keys().contains("delaytime")){ delayTime = m_gsettings->get("delaytime").toInt(); + qCInfo(DDE_SHELL) << "DelayTime : " << delayTime; + } +#else + if (m_dConfig) { + delayTime = m_dConfig->value("delayTime", 500).toInt(); qInfo() << "delayTime : " << delayTime; } +#endif if (delayTime < 0) { delayTime = 500; } + WarningContent::instance()->tryGrabKeyboard(); QTimer::singleShot(delayTime, this, [=] { + // 待机休眠前设置Locked为true,避免刚唤醒时locked状态不对 + if (sleepLock) { + setLocked(true); + } m_sessionManagerInter->RequestSuspend(); }); } @@ -374,36 +553,72 @@ void LockWorker::doPowerAction(const SessionBaseModel::PowerAction action) case SessionBaseModel::PowerAction::RequireHibernate: { m_model->setIsBlackMode(true); - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + int delayTime = 500; +#ifndef ENABLE_DSS_SNIPE if(m_gsettings && m_gsettings->keys().contains("delaytime")){ delayTime = m_gsettings->get("delaytime").toInt(); - qInfo() << " delayTime : " << delayTime; + qCInfo(DDE_SHELL) << "DelayTime : " << delayTime; + } +#else + if (m_dConfig) { + delayTime = m_dConfig->value("delayTime", 500).toInt(); + qInfo() << "delayTime : " << delayTime; } +#endif if (delayTime < 0) { delayTime = 500; } - QTimer::singleShot(delayTime, this, [=] { - m_sessionManagerInter->RequestHibernate(); - }); + if (canHibernate()){ + WarningContent::instance()->tryGrabKeyboard(); + QTimer::singleShot(delayTime, this, [=] { + // 待机休眠前设置Locked为true,避免刚唤醒时locked状态不对 + if (sleepLock) { + setLocked(true); + } + m_sessionManagerInter->RequestHibernate(); + }); + } } break; - case SessionBaseModel::PowerAction::RequireRestart: - if (!isLocked()) { + case SessionBaseModel::PowerAction::RequireRestart: { + m_model->setShutdownMode(true); + auto gsCheckPwd = m_model->gsCheckpwd(); + if (!isLocked() || m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode || !gsCheckPwd) { m_sessionManagerInter->RequestReboot(); } else { createAuthentication(m_account); m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ConfirmPasswordMode); } + + if (m_model->visibleShutdownWhenRebootOrShutdown()) { + return; + } + + if (!gsCheckPwd) + m_model->setVisible(false); + return; - case SessionBaseModel::PowerAction::RequireShutdown: - if (!isLocked()) { + } + case SessionBaseModel::PowerAction::RequireShutdown: { + m_model->setShutdownMode(true); + auto gsCheckPwd = m_model->gsCheckpwd(); + if (!isLocked() || m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode || !gsCheckPwd) { m_sessionManagerInter->RequestShutdown(); } else { createAuthentication(m_account); m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ConfirmPasswordMode); } + + if (m_model->visibleShutdownWhenRebootOrShutdown()) { + return; + } + + if (!gsCheckPwd) + m_model->setVisible(false); + return; + } case SessionBaseModel::PowerAction::RequireLock: m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); createAuthentication(m_model->currentUser()->name()); @@ -413,10 +628,23 @@ void LockWorker::doPowerAction(const SessionBaseModel::PowerAction action) return; case SessionBaseModel::PowerAction::RequireSwitchSystem: m_switchosInterface->setOsFlag(!m_switchosInterface->getOsFlag()); - QTimer::singleShot(200, this, [=] { m_sessionManagerInter->RequestReboot(); }); + QTimer::singleShot(200, this, [this] { m_sessionManagerInter->RequestReboot(); }); break; case SessionBaseModel::PowerAction::RequireSwitchUser: - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); + if (m_model->userlistVisible()) { + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); + } else { + std::shared_ptr user_ptr = m_model->findUserByName("..."); + if (user_ptr) { + switchToUser(user_ptr); + } + } + break; + case SessionBaseModel::PowerAction::RequireUpdateRestart: + UpdateWorker::instance()->doUpdate(false); + break; + case SessionBaseModel::PowerAction::RequireUpdateShutdown: + UpdateWorker::instance()->doUpdate(true); break; default: break; @@ -425,6 +653,24 @@ void LockWorker::doPowerAction(const SessionBaseModel::PowerAction action) m_model->setPowerAction(SessionBaseModel::PowerAction::None); } + +bool LockWorker::isCheckPwdBeforeRebootOrShut() +{ +#ifndef ENABLE_DSS_SNIPE + if (QGSettings::isSchemaInstalled("com.deepin.dde.session-shell")) { + QGSettings updateSettings("com.deepin.dde.session-shell", QByteArray(), this); + if (updateSettings.keys().contains("checkpwd")) { + return updateSettings.get("checkpwd").toBool(); + } + } +#else + if (m_dConfig) { + return m_dConfig->value("checkpwd", false).toBool(); + } +#endif + return false; +} + /** * @brief 将当前用户的信息保存到 LockService 服务 * @@ -432,30 +678,28 @@ void LockWorker::doPowerAction(const SessionBaseModel::PowerAction action) */ void LockWorker::setCurrentUser(const std::shared_ptr user) { - qInfo() << "Set current user: " << user->name(); + qCInfo(DDE_SHELL) << "Set current user: " << user->name(); QJsonObject json; - json["AuthType"] = user->lastAuthType(); + json["AuthType"] = static_cast(user->lastAuthType()); json["Name"] = user->name(); json["Type"] = user->type(); json["Uid"] = static_cast(user->uid()); + json["LastCustomAuth"] = user->lastCustomAuth(); // 上一次认证通过自定义认证类型 m_lockInter->SwitchToUser(QString(QJsonDocument(json).toJson(QJsonDocument::Compact))); } void LockWorker::switchToUser(std::shared_ptr user) { - qDebug() << "LockWorker::switchToUser:" << m_account << user->name(); + // 发生用户切换时锁住 + setLocked(true); + + qCDebug(DDE_SHELL) << "LockWorker::switchToUser:" << m_account << user->name(); if (user->name() == m_account || *user == *m_model->currentUser()) { - qInfo() << "switch to current user:" << user->name() << user->isLogin(); - if (!m_authFramework->authSessionExist(m_account)) { - createAuthentication(user->name()); - } else { - endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); - createAuthentication(m_account); - } + qCInfo(DDE_SHELL) << "Switch to current user:" << user->name() << user->isLogin(); + createAuthentication(user->name()); return; } else { - qInfo() << "switch user from" << m_account << "to" << user->name() << user->isLogin(); + qCInfo(DDE_SHELL) << "Switch user from" << m_account << "to" << user->name() << ", login: " << user->isLogin(); endAuthentication(m_account, AT_All); setCurrentUser(user); } @@ -513,17 +757,42 @@ void LockWorker::setLocked(const bool locked) */ void LockWorker::createAuthentication(const QString &account) { - qInfo() << "LockWorker::createAuthentication:" << account; + qCInfo(DDE_SHELL) << "Account:" << account; QString userPath = m_accountsInter->FindUserByName(account); if (!userPath.startsWith("/")) { - qWarning() << userPath; + qCWarning(DDE_SHELL) << "User's path is invalid:" << userPath; return; } + // 如果验证会话已经存在,销毁后重新开启验证 + if (m_authFramework->authSessionExist(account) || m_authFramework->IsUsingPamAuth()) { + endAuthentication(account, AT_All); + destroyAuthentication(account); + } + // 同步密码过期的信息 std::shared_ptr user_ptr = m_model->findUserByName(account); if (user_ptr) { user_ptr->updatePasswordExpiredInfo(); + + if (user_ptr->isNoPasswordLogin()) { + qCInfo(DDE_SHELL) << "User is no password login"; + // 无密码登录锁定后也属于锁屏,需要设置lock属性 +#ifndef ENABLE_DSS_SNIPE + if (m_model->getPowerGSettings("", "sleepLock").toBool()) { +#else + if (isSleepLock()) { +#endif + setLocked(true); + } else if (m_model->isQuickLoginProcess()) { + //若此次程序拉起为快速登录流程,需要锁屏 + qCInfo(DDE_SHELL) << "Quick login requires screen lock"; + setLocked(true); + m_model->setQuickLoginProcess(false); + } + + return; + } } m_account = account; @@ -545,15 +814,15 @@ void LockWorker::createAuthentication(const QString &account) * * @param account */ -void LockWorker::destoryAuthentication(const QString &account) +void LockWorker::destroyAuthentication(const QString &account) { - qInfo() << "LockWorker::destoryAuthentication:" << account; + qCInfo(DDE_SHELL) << "Destroy authentication, account:" << account; switch (m_model->getAuthProperty().FrameworkState) { case Available: - m_authFramework->DestoryAuthController(account); + m_authFramework->DestroyAuthController(account); break; default: - m_authFramework->DestoryAuthenticate(); + m_authFramework->DestroyAuthenticate(); break; } } @@ -565,9 +834,9 @@ void LockWorker::destoryAuthentication(const QString &account) * @param authType 认证类型(可传入一种或多种) * @param timeout 设定超时时间(默认 -1) */ -void LockWorker::startAuthentication(const QString &account, const int authType) +void LockWorker::startAuthentication(const QString &account, const AuthFlags authType) { - qInfo() << "LockWorker::startAuthentication:" << account << authType; + qCInfo(DDE_SHELL) << "Start authentication, account:" << account << ", auth types:" << authType; switch (m_model->getAuthProperty().FrameworkState) { case Available: m_authFramework->StartAuthentication(account, authType, -1); @@ -585,9 +854,9 @@ void LockWorker::startAuthentication(const QString &account, const int authType) * @param authType 认证类型 * @param token 密文 */ -void LockWorker::sendTokenToAuth(const QString &account, const int authType, const QString &token) +void LockWorker::sendTokenToAuth(const QString &account, const AuthType authType, const QString &token) { - qInfo() << "LockWorker::sendTokenToAuth:" << account << authType; + qCInfo(DDE_SHELL) << "Send token to auth, account: " << account << ", auth type: " << authType; switch (m_model->getAuthProperty().FrameworkState) { case Available: m_authFramework->SendTokenToAuth(account, authType, token); @@ -604,9 +873,9 @@ void LockWorker::sendTokenToAuth(const QString &account, const int authType, con * @param account 账户 * @param authType 认证类型 */ -void LockWorker::endAuthentication(const QString &account, const int authType) +void LockWorker::endAuthentication(const QString &account, const AuthFlags authType) { - qDebug() << "LockWorker::endAuthentication:" << account << authType; + qCInfo(DDE_SHELL) << "End authentication, account:" << account << ", auth type:" << authType; switch (m_model->getAuthProperty().FrameworkState) { case Available: m_authFramework->EndAuthentication(account, authType); @@ -616,6 +885,14 @@ void LockWorker::endAuthentication(const QString &account, const int authType) } } +void LockWorker::onEndAuthentication(const QString &account, const AuthFlags authType) +{ + endAuthentication(account, authType); + if (AT_All == authType) { + destroyAuthentication(account); + } +} + void LockWorker::lockServiceEvent(quint32 eventType, quint32 pid, const QString &username, const QString &message) { Q_UNUSED(pid) @@ -639,17 +916,17 @@ void LockWorker::lockServiceEvent(quint32 eventType, quint32 pid, const QString switch (eventType) { case DBusLockService::PromptQuestion: - qWarning() << "prompt question from pam: " << message; + qCWarning(DDE_SHELL) << "Prompt question from pam: " << message; emit m_model->authFailedMessage(message); break; case DBusLockService::PromptSecret: - qWarning() << "prompt secret from pam: " << message; + qCWarning(DDE_SHELL) << "Prompt secret from pam: " << message; if (m_isThumbAuth && !msg.isEmpty()) { emit m_model->authFailedMessage(msg); } break; case DBusLockService::ErrorMsg: - qWarning() << "error message from pam: " << message; + qCWarning(DDE_SHELL) << "Error message from pam: " << message; if (msg == "Failed to match fingerprint") { emit m_model->authFailedTipsMessage(tr("Failed to match fingerprint")); emit m_model->authFailedMessage(""); @@ -671,27 +948,19 @@ void LockWorker::lockServiceEvent(quint32 eventType, quint32 pid, const QString void LockWorker::onAuthFinished() { - m_model->setVisible(false); onUnlockFinished(true); setCurrentUser(m_model->currentUser()); } void LockWorker::onUnlockFinished(bool unlocked) { - qInfo() << "LockWorker::onUnlockFinished -- unlocked state : " << unlocked; + qCInfo(DDE_SHELL) << "Unlock finished, is unlocked: " << unlocked; m_authenticating = false; //To Do: 最好的方案是修改同步后端认证信息的代码设计 if (m_model->currentModeState() == SessionBaseModel::ModeStatus::UserMode) m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); - - // if (!unlocked && m_authFramework->GetAuthType() == AuthFlag::Password) { - // qWarning() << "Authorization password failed!"; - // emit m_model->authFailedTipsMessage(tr("Wrong Password")); - // return; - // } - switch (m_model->powerAction()) { case SessionBaseModel::PowerAction::RequireRestart: if (unlocked) { @@ -720,23 +989,82 @@ void LockWorker::restartResetSessionTimer() void LockWorker::disableGlobalShortcutsForWayland(const bool enable) { + qCInfo(DDE_SHELL) << "Disable global shortcuts for wayland: " << enable; if (m_kwinInter == nullptr || m_kglobalaccelInter == nullptr) { return; } if (!m_kwinInter->isValid()) { - qWarning() << "kwinInter is not valid"; + qCWarning(DDE_SHELL) << "Kwin interface is not valid"; return; } QDBusReply reply = m_kwinInter->call("disableGlobalShortcutsForClient", enable); if (!reply.isValid()) { - qWarning() << "call disableGlobalShortcutsForClient failed" << reply.error(); + qCWarning(DDE_SHELL) << "Call `disableGlobalShortcutsForClient` failed, error: " << reply.error(); } if (!m_kglobalaccelInter->isValid()) { - qWarning() << "kglobalaccelInter is not valid"; + qCWarning(DDE_SHELL) << "Global accel interface is not valid"; return; } - reply = m_kglobalaccelInter->call("setActiveByUniqueName", "Screenshot", true); - if (!reply.isValid()) { - qWarning() << "call setActiveByUniqueName failed" << reply.error(); + const QStringList &shortCutList = DConfigHelper::instance() + ->getConfig("enableShortcutForLock", QStringList()) + .toStringList(); + if (!shortCutList.isEmpty()) { + foreach (const QString &shortcut, shortCutList) { + reply = m_kglobalaccelInter->call("setActiveByUniqueName", shortcut, true); + if (!reply.isValid()) { + qCWarning(DDE_SHELL) << "Call `setActiveByUniqueName` failed, error: " << reply.error(); + } + } + } else { + qCWarning(DDE_SHELL) << "There is no shortcut should be enabled!"; + } +} + +void LockWorker::checkAccount(const QString &account, bool switchUser) +{ + Q_UNUSED(account) + Q_UNUSED(switchUser) + + if (m_model->currentUser() && m_model->currentUser()->isNoPasswordLogin()) { + qCInfo(DDE_SHELL) << "Current user has set 'no password login' : " << account; + + authFinishedAction(); + } +} + +void LockWorker::authFinishedAction() +{ + if ((m_model->powerAction() == SessionBaseModel::PowerAction::RequireRestart + || m_model->powerAction() == SessionBaseModel::PowerAction::RequireShutdown) + && WarningContent::instance()->supportDelayOrWait()) { + qCDebug(DDE_SHELL) << "return to warningcontent"; + FullScreenBackground::setContent(WarningContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::WarningContent); + } else { + qCDebug(DDE_SHELL) << "hide main window"; + m_model->setVisible(false); + } + onAuthFinished(); + enableZoneDetected(true); +} + +void LockWorker::onNoPasswordLoginChanged(const QString &account, bool noPassword) +{ + qCDebug(DDE_SHELL) << "user:" << account << ", noPassword:" << noPassword << ", visible :" << m_model->visible(); + if(m_model->currentUser()->name() == account && m_model->visible()) { + if (m_model->currentModeState() != SessionBaseModel::ShutDownMode && m_model->currentModeState() != SessionBaseModel::UserMode) { + createAuthentication(account); + } + } +} + +void LockWorker::sendExtraInfo(const QString &account, AuthCommon::AuthType authType, const QString &info) +{ + switch (m_model->getAuthProperty().FrameworkState) { + case Available: + m_authFramework->sendExtraInfo(account, authType, info); + break; + default: + break; } } diff --git a/src/dde-lock/lockworker.h b/src/dde-lock/lockworker.h index 048b54f8..2c0bef68 100644 --- a/src/dde-lock/lockworker.h +++ b/src/dde-lock/lockworker.h @@ -1,18 +1,21 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef LOCKWORKER_H #define LOCKWORKER_H #include "authinterface.h" #include "dbushotzone.h" #include "dbuslockservice.h" -#include "dbuslogin1manager.h" #include "deepinauthframework.h" #include "sessionbasemodel.h" #include "switchos_interface.h" #include "userinfo.h" #include -#include +#ifndef ENABLE_DSS_SNIPE #include #include #include @@ -22,6 +25,17 @@ using AccountsInter = com::deepin::daemon::Accounts; using UserInter = com::deepin::daemon::accounts::User; using LoginedInter = com::deepin::daemon::Logined; using SessionManagerInter = com::deepin::SessionManager; +#else +#include "accounts1interface.h" +#include "loginedinterface.h" +#include "userinterface.h" +#include "sessionmanager1interface.h" + +using AccountsInter = org::deepin::dde::Accounts1; +using UserInter = org::deepin::dde::accounts1::User; +using LoginedInter = org::deepin::dde::Logined; +using SessionManagerInter = org::deepin::dde::SessionManager1; +#endif class SessionBaseModel; class LockWorker : public Auth::AuthInterface @@ -37,10 +51,11 @@ class LockWorker : public Auth::AuthInterface public slots: /* New authentication framework */ void createAuthentication(const QString &account); - void destoryAuthentication(const QString &account); - void startAuthentication(const QString &account, const int authType); - void endAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); + void destroyAuthentication(const QString &account); + void startAuthentication(const QString &account, const AuthFlags authType); + void endAuthentication(const QString &account, const AuthFlags authType); + void sendTokenToAuth(const QString &account, const AuthType authType, const QString &token); + void onEndAuthentication(const QString &account, const AuthFlags authType); void switchToUser(std::shared_ptr user) override; void restartResetSessionTimer(); @@ -48,6 +63,12 @@ public slots: void onAuthStateChanged(const int type, const int state, const QString &message); void disableGlobalShortcutsForWayland(const bool enable); + void checkAccount(const QString &account, bool switchUser); + void authFinishedAction(); + + void onNoPasswordLoginChanged(const QString &account, bool noPassword); + void sendExtraInfo(const QString &account, AuthCommon::AuthType authType, const QString &info); + void setLocked(const bool locked); private: void initConnections(); @@ -56,12 +77,13 @@ public slots: void doPowerAction(const SessionBaseModel::PowerAction action); void setCurrentUser(const std::shared_ptr user); - void setLocked(const bool locked); // lock void lockServiceEvent(quint32 eventType, quint32 pid, const QString &username, const QString &message); void onUnlockFinished(bool unlocked); + bool isCheckPwdBeforeRebootOrShut(); + private: bool m_authenticating; bool m_isThumbAuth; @@ -70,11 +92,12 @@ public slots: DBusHotzone *m_hotZoneInter; QTimer *m_resetSessionTimer; QTimer *m_limitsUpdateTimer; + QTimer *m_wakeUpAuthTimer; QString m_password; QMap, bool> m_lockUser; SessionManagerInter *m_sessionManagerInter; HuaWeiSwitchOSInterface *m_switchosInterface = nullptr; - bool m_canAuthenticate = false; + QString m_account; QDBusInterface *m_kglobalaccelInter; QDBusInterface *m_kwinInter; diff --git a/src/dde-lock/securityloaderhelper.cpp b/src/dde-lock/securityloaderhelper.cpp new file mode 100644 index 00000000..4f997f51 --- /dev/null +++ b/src/dde-lock/securityloaderhelper.cpp @@ -0,0 +1,217 @@ +// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "securityloaderhelper.h" +#include "dbusconstant.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(secLoader, "org.deepin.dde.lock.securityloader") + +const QString SecurityLoaderHelper::DEFAULT_CONFIG_PATH = ":/files/permission-interfaces/auth.json"; + +SecurityLoaderHelper::SecurityLoaderHelper(QObject *parent) + : QObject(parent) +{ +} + +SecurityLoaderHelper::~SecurityLoaderHelper() {} + +SecurityLoaderHelper &SecurityLoaderHelper::instance() +{ + static SecurityLoaderHelper instance; + return instance; +} + +void SecurityLoaderHelper::doSecurityLoader(int fd1, int fd2) +{ + if (fd1 < 0 || fd2 < 0) { + qCWarning(secLoader) << "Not loaded by loader, skipping handshake"; + return; + } + + qCInfo(secLoader) << "Detected loader injection: fd1=" << fd1 << "fd2=" << fd2; + + loadConfig(); + // appendCurrentUserAccountsUserDest(); + if (!performHandshake(fd1, fd2)) { + qCWarning(secLoader) << "Security loader handshake failed"; + } +} + +void SecurityLoaderHelper::loadConfig(const QString &configPath) +{ + QString path = configPath.isEmpty() ? DEFAULT_CONFIG_PATH : configPath; + + qCInfo(secLoader) << "Loading permission config from:" << path; + + m_destList = QJsonArray(); + parseJsonFile(path); + + qCInfo(secLoader) << "Loaded" << m_destList.size() << "D-Bus interfaces to authorize"; +} + +void SecurityLoaderHelper::parseJsonFile(const QString &filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qCWarning(secLoader) << "Cannot open file:" << filePath; + return; + } + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error); + file.close(); + + if (error.error != QJsonParseError::NoError) { + qCWarning(secLoader) << "JSON parse error in" << filePath << ":" << error.errorString(); + return; + } + + QJsonObject root = doc.object(); + if (!root.contains("DestList") || !root["DestList"].isArray()) { + qCWarning(secLoader) << "Invalid config format in" << filePath << ": missing DestList"; + return; + } + + for (const auto &item : root["DestList"].toArray()) { + appendDest(item.toObject()); + } +} + +void SecurityLoaderHelper::appendDest(const QJsonObject &dest) +{ + const QString dbusName = dest["DbusName"].toString(); + const QString dbusPath = dest["DbusPath"].toString(); + const QString dbusInterface = dest["DbusInterface"].toString(); + + if (dbusName.isEmpty() || dbusPath.isEmpty() || dbusInterface.isEmpty()) { + qCWarning(secLoader) << "Skip invalid D-Bus destination:" << dest; + return; + } + + for (const auto &existing : m_destList) { + const QJsonObject current = existing.toObject(); + if (current["DbusName"] == dbusName && + current["DbusPath"] == dbusPath && + current["DbusInterface"] == dbusInterface) { + return; + } + } + + m_destList.append(dest); + qCInfo(secLoader) << " Added:" << dbusName << dbusPath << dbusInterface; +} + +void SecurityLoaderHelper::appendCurrentUserAccountsUserDest() +{ + const QString userPath = currentUserAccountsPath(); + if (userPath.isEmpty()) { + qCWarning(secLoader) << "Cannot resolve current user's Accounts.User path"; + return; + } + + QJsonObject dest; + dest["DbusName"] = DSS_DBUS::accountsService; + dest["DbusPath"] = userPath; + dest["DbusInterface"] = DSS_DBUS::accountsUserInterface; + appendDest(dest); +} + +QString SecurityLoaderHelper::currentUserAccountsPath() const +{ + QDBusConnection systemBus = QDBusConnection::systemBus(); + if (!systemBus.isConnected()) { + qCWarning(secLoader) << "Cannot connect to system bus when resolving current user path"; + return {}; + } + + QDBusInterface accountsInterface(DSS_DBUS::accountsService, DSS_DBUS::accountsPath, DSS_DBUS::accountsService, systemBus); + if (!accountsInterface.isValid()) { + qCWarning(secLoader) << "Accounts interface invalid when resolving current user path:" + << accountsInterface.lastError().message(); + return {}; + } + + QDBusReply reply = accountsInterface.call(QStringLiteral("FindUserById"), QString::number(getuid())); + if (!reply.isValid()) { + qCWarning(secLoader) << "FindUserById failed when resolving current user path:" + << reply.error().message(); + return {}; + } + + return reply.value(); +} + +bool SecurityLoaderHelper::performHandshake(int fd1, int fd2) +{ + if (m_destList.isEmpty()) { + qCInfo(secLoader) << "No D-Bus interfaces loaded, skipping handshake"; + return true; + } + + qCInfo(secLoader) << "Performing loader handshake..."; + + QDBusConnection systemBus = QDBusConnection::systemBus(); + if (!systemBus.isConnected()) { + qCWarning(secLoader) << "Cannot connect to system bus"; + return false; + } + // 偶现dbus的 unique name 发生变化,Qt的systemBus.baseService()实际上并未把dbus注册到总线上,要调用一下方法才行 + systemBus.interface()->isServiceRegistered("org.freedesktop.DBus"); + QString uniqueName = systemBus.baseService(); + qCInfo(secLoader) << "System Bus UniqueName:" << uniqueName; + + QJsonObject request; + request["UniqueName"] = uniqueName; + request["DestList"] = m_destList; + + QJsonDocument doc(request); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + qCInfo(secLoader) << "Sending request with" << m_destList.size() << "interfaces"; + + QFile fd1File; + if (!fd1File.open(fd1, QIODevice::WriteOnly)) { + qCWarning(secLoader) << "Cannot open fd1 for writing"; + return false; + } + fd1File.write(jsonData); + fd1File.close(); + qCInfo(secLoader) << "Sent authorization request to loader"; + + QFile fd2File; + if (!fd2File.open(fd2, QIODevice::ReadOnly)) { + qCWarning(secLoader) << "Cannot open fd2 for reading"; + return false; + } + + QByteArray response = fd2File.readAll(); + fd2File.close(); + + QJsonParseError parseError; + QJsonDocument responseDoc = QJsonDocument::fromJson(response, &parseError); + if (parseError.error != QJsonParseError::NoError) { + qCWarning(secLoader) << "Invalid JSON response from loader:" << parseError.errorString(); + return false; + } + + QJsonObject result = responseDoc.object(); + if (result["Result"].toBool()) { + qCInfo(secLoader) << "Loader handshake completed successfully"; + return true; + } else { + qCWarning(secLoader) << "Loader authorization response:" << result["Message"].toString(); + return false; + } +} diff --git a/src/dde-lock/securityloaderhelper.h b/src/dde-lock/securityloaderhelper.h new file mode 100644 index 00000000..c2bf6b41 --- /dev/null +++ b/src/dde-lock/securityloaderhelper.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef SECURITYLOADERHELPER_H +#define SECURITYLOADERHELPER_H + +#include +#include + +class SecurityLoaderHelper : public QObject +{ + Q_OBJECT + +public: + static SecurityLoaderHelper &instance(); + void doSecurityLoader(int fd1, int fd2); + +private: + explicit SecurityLoaderHelper(QObject *parent = nullptr); + ~SecurityLoaderHelper(); + + SecurityLoaderHelper(const SecurityLoaderHelper &) = delete; + SecurityLoaderHelper &operator=(const SecurityLoaderHelper &) = delete; + + void loadConfig(const QString &configPath = QString()); + void parseJsonFile(const QString &filePath); + void appendDest(const QJsonObject &dest); + void appendCurrentUserAccountsUserDest(); + QString currentUserAccountsPath() const; + bool performHandshake(int fd1, int fd2); + +private: + QJsonArray m_destList; + static const QString DEFAULT_CONFIG_PATH; +}; + +#endif // SECURITYLOADERHELPER_H diff --git a/src/dde-lock/updateworker.cpp b/src/dde-lock/updateworker.cpp new file mode 100644 index 00000000..bf2c6d3d --- /dev/null +++ b/src/dde-lock/updateworker.cpp @@ -0,0 +1,104 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "updateworker.h" +#include "constants.h" +#include "dbusconstant.h" + +#include +#include +#include +#include + +#include + +UpdateWorker::UpdateWorker(QObject* parent) + : QObject(parent) +{ + +} + +void UpdateWorker::doUpdate(bool powerOff) +{ + qCInfo(DDE_SHELL) << "Start update progress"; + + // 检查电量 + const bool powerIsOK = checkPower(); + if (!powerIsOK) { + Q_EMIT requestExitUpdating(); + DDBusSender() + .service("org.freedesktop.Notifications") + .path("/org/freedesktop/Notifications") + .interface("org.freedesktop.Notifications") + .method(QString("Notify")) +#ifndef ENABLE_DSS_SNIPE + .arg(tr("Update")) + .arg(static_cast(0)) + .arg(QString("package-updated-failed")) +#else + .arg(QString("org.deepin.dde.control-center")) + .arg(static_cast(0)) + .arg(QString()) +#endif + .arg(QString("")) + .arg(tr("Please plug in and then install updates.")) + .arg(QStringList()) + .arg(QVariantMap()) + .arg(5000) + .call(); + + qCWarning(DDE_SHELL) << "Low power, exit update progress"; + return; + } + + qCInfo(DDE_SHELL) << "Power check passed"; + + prepareFullScreenUpgrade(powerOff); +} + +bool UpdateWorker::checkPower() +{ + qCInfo(DDE_SHELL) << "Check power"; + PowerInter powerInter(DSS_DBUS::powerService, DSS_DBUS::powerPath, QDBusConnection::systemBus(), this); + bool onBattery = powerInter.onBattery(); + if (!onBattery) { + qCInfo(DDE_SHELL) << "No battery"; + return true; + } + + double data = powerInter.batteryPercentage(); + int batteryPercentage = uint(qMin(100.0, qMax(0.0, data))); + qCInfo(DDE_SHELL) << "Battery percentage: " << batteryPercentage; + return batteryPercentage >= 60; +} + +void UpdateWorker::prepareFullScreenUpgrade(bool powerOff) +{ + qCInfo(DDE_SHELL) << "Do update after restart lightdm"; + + QJsonObject content; + QDBusInterface managerInter(DSS_DBUS::lastoreService, + DSS_DBUS::lastorePath, + DSS_DBUS::lastoreInterface, + QDBusConnection::systemBus()); + content["DoUpgradeMode"] = managerInter.property("CheckUpdateMode").toInt(); + content["IsPowerOff"] = powerOff; + + QJsonDocument jsonDoc; + jsonDoc.setObject(content); + + const QString& arg = jsonDoc.toJson(); + qCInfo(DDE_SHELL) << "Call function `PrepareFullScreenUpgrade` with arg:" << arg; + + QDBusPendingReply reply = managerInter.asyncCall("PrepareFullScreenUpgrade", arg); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [reply, watcher] { + watcher->deleteLater(); + if (reply.isValid()) { + qCInfo(DDE_SHELL) << "Call `PrepareFullScreenUpgrade` function successfully, quit myself"; + } else { + qCWarning(DDE_SHELL) << "Call `PrepareFullScreenUpgrade` function failed, error:" << reply.error().message(); + } + }); +} diff --git a/src/dde-lock/updateworker.h b/src/dde-lock/updateworker.h new file mode 100644 index 00000000..9bd39197 --- /dev/null +++ b/src/dde-lock/updateworker.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef UPDATECTRL_H +#define UPDATECTRL_H + +#ifndef ENABLE_DSS_SNIPE +#include + +using PowerInter = com::deepin::system::Power; +#else +#include "systempower1interface.h" + +using PowerInter = org::deepin::dde::Power1; +#endif +class UpdateWorker : public QObject +{ + Q_OBJECT + +public: + static UpdateWorker *instance() { + static UpdateWorker *pIns = nullptr; + if (!pIns) { + pIns = new UpdateWorker(); + } + return pIns; + }; + + void doUpdate(bool powerOff); + +Q_SIGNALS: + void requestExitUpdating(); + +private: + explicit UpdateWorker(QObject *parent = nullptr); + + bool checkPower(); + void prepareFullScreenUpgrade(bool powerOff); +}; + +#endif // UPDATECTRL_H diff --git a/src/global_util/accessibilitycheckerex.cpp b/src/global_util/accessibilitycheckerex.cpp index f4a094a4..eb2a1437 100644 --- a/src/global_util/accessibilitycheckerex.cpp +++ b/src/global_util/accessibilitycheckerex.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "accessibilitycheckerex.h" #if defined(DSS_CHECK_ACCESSIBILITY) && defined(QT_DEBUG) diff --git a/src/global_util/accessibilitycheckerex.h b/src/global_util/accessibilitycheckerex.h index bf13b9db..df73eea6 100644 --- a/src/global_util/accessibilitycheckerex.h +++ b/src/global_util/accessibilitycheckerex.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef ACCESSIBILITYCHECKEREX_H #define ACCESSIBILITYCHECKEREX_H diff --git a/src/global_util/appeventfilter.cpp b/src/global_util/appeventfilter.cpp index a4477f10..e9ec12e7 100644 --- a/src/global_util/appeventfilter.cpp +++ b/src/global_util/appeventfilter.cpp @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2018 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: fanpengcheng - * - * Maintainer: fanpengcheng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "appeventfilter.h" AppEventFilter::AppEventFilter(QObject *parent) : QObject(parent) diff --git a/src/global_util/appeventfilter.h b/src/global_util/appeventfilter.h index 22c10cb7..e0530b2e 100644 --- a/src/global_util/appeventfilter.h +++ b/src/global_util/appeventfilter.h @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2018 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: fanpengcheng - * - * Maintainer: fanpengcheng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef APPEVENTFILTER_H #define APPEVENTFILTER_H diff --git a/src/global_util/backgroundhandlerThread.cpp b/src/global_util/backgroundhandlerThread.cpp new file mode 100644 index 00000000..7333a3ea --- /dev/null +++ b/src/global_util/backgroundhandlerThread.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + + +#include "backgroundhandlerThread.h" +#include "public_func.h" + +#include + +BackgroundHandlerThread::BackgroundHandlerThread(QObject *parent) + : QThread(parent) +{ + +} + +void BackgroundHandlerThread::setBackgroundInfo(const QString &path, const QSize &size, const qreal &devicePixelRatioF) +{ + m_path = path; + m_targetSize = size; + m_devicePixelRatioF = devicePixelRatioF; +} + +void BackgroundHandlerThread::run() +{ + handle(); +} + +QPixmap BackgroundHandlerThread::handleBackground(const QString &path, const QSize &size, const qreal &devicePixelRatioF) +{ + QPixmap pixmap; + pixmap = loadPixmap(path); + + pixmap = pixmap.scaled(size, Qt::KeepAspectRatioByExpanding, Qt::FastTransformation); + pixmap = pixmap.copy(QRect((pixmap.width() - size.width()) / 2, + (pixmap.height() - size.height()) / 2, + size.width(), + size.height())); + + // draw pix to widget, so pix need set pixel ratio from qwidget devicepixelratioF + pixmap.setDevicePixelRatio(devicePixelRatioF); + + return pixmap; +} + +void BackgroundHandlerThread::handle() +{ + auto pixmap = handleBackground(m_path, m_targetSize, m_devicePixelRatioF); + emit backgroundHandled(pixmap); +} diff --git a/src/global_util/backgroundhandlerThread.h b/src/global_util/backgroundhandlerThread.h new file mode 100644 index 00000000..88bbd4b4 --- /dev/null +++ b/src/global_util/backgroundhandlerThread.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DDE_SESSION_SHELL_BACKGROUNDHANDLERTHREAD_H +#define DDE_SESSION_SHELL_BACKGROUNDHANDLERTHREAD_H + +#include +#include +#include + +class BackgroundHandlerThread : public QThread +{ + Q_OBJECT +public: + explicit BackgroundHandlerThread(QObject *parent = nullptr); + + void setBackgroundInfo(const QString &path, const QSize &size, const qreal &devicePixelRatioF); + + // 直接调用handle则不会通过线程处理图片 + void handle(); + +signals: + void backgroundHandled(const QPixmap &pixmap); + +protected: + void run() override; + +private: + static QPixmap handleBackground(const QString &path, const QSize &size, const qreal &devicePixelRatioF); + +private: + QString m_path; + QSize m_targetSize; + qreal m_devicePixelRatioF; +}; + +#endif //DDE_SESSION_SHELL_BACKGROUNDHANDLERTHREAD_H diff --git a/src/global_util/constants.h b/src/global_util/constants.h index 5ff3e5ca..8f0d233d 100644 --- a/src/global_util/constants.h +++ b/src/global_util/constants.h @@ -1,61 +1,48 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef CONSTANTS_H #define CONSTANTS_H +#include + #include #include +#include +Q_DECLARE_LOGGING_CATEGORY(DDE_SHELL) namespace DDESESSIONCC { static const QString CONFIG_FILE("/var/lib/AccountsService/deepin/users/"); static const QString DEFAULT_CURSOR_THEME("/usr/share/icons/default/index.theme"); static const QString LAST_USER_CONFIG("/var/lib/lightdm/lightdm-deepin-greeter"); -static const int PASSWDLINEEIDT_WIDTH = 280; -static const int PASSWDLINEEDIT_HEIGHT = 36; +static const int PASSWD_EDIT_WIDTH = 280; +static const int PASSWD_EDIT_HEIGHT = 36; static const int LOCK_CONTENT_TOP_WIDGET_HEIGHT = 132; // 顶部控件(日期)的高度 -static const int LOCK_CONTENT_CENTER_LAYOUT_MARGIN = 33; // SessionBaseWindow 中mainlayout的上下间隔 +static const int LOCK_CONTENT_CENTER_LAYOUT_MARGIN = 33; // SessionBaseWindow 中main layout的上下间隔 static const int BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT = 42; // 生物认证状态占位高度 -static const int BIO_AUTH_STATE_BOTTOM_SPACING = 40; // 生物识别状态底部间隔 -static const int CHOOSE_AUTH_TYPE_BUTTON_PLACE_HOLDER_HEIGHT = 50; // 认证类型选择按钮占位高度 +static const int CHOOSE_AUTH_TYPE_PLACE_HOLDER_HEIGHT = 36; // 认证类型选择按钮占位高度 +static const int BIO_AUTH_STATE_BOTTOM_SPACING = 30; // 生物识别状态底部间隔 static const int CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING = 40; // 认证类型选择按钮底部间隔 static const double AUTH_WIDGET_TOP_SPACING_PERCENT = 0.35; // 认证窗口顶部间隔占整个屏幕的百分比 -static const int LAYOUTBUTTON_HEIGHT = 34; -static const int KEYBOARDLAYOUT_WIDTH = 200; +static const int LAYOUT_BUTTON_HEIGHT = 34; +static const int KEYBOARD_LAYOUT_WIDTH = 200; -static const int CapslockWarningWidth = 23; -static const int CapslockWarningRightMargin = 8; +static const int CAPS_LOCK_STATUS_WIDTH = 23; +static const int CAPS_LOCK_STATUS_RIGHT_MARGIN = 8; static const int BASE_SCREEN_HEIGHT = 1080; static const int MIN_AUTH_WIDGET_HEIGHT = 276; // 密码验证时整个登录控件的大小,默认为最小高度(不考虑无密码登录的情况,稍许影响) const QStringList session_ui_configs { "/etc/lightdm/lightdm-deepin-greeter.conf", "/etc/deepin/dde-session-ui.conf", +#ifdef ENABLE_DSS_SNIPE + "/var/lib/dde-session-shell/dde-session-shell.conf", +#else "/usr/share/dde-session-shell/dde-session-shell.conf", +#endif "/usr/share/dde-session-ui/dde-session-ui.conf" }; @@ -74,6 +61,35 @@ enum AuthFactorType { SingleAuthFactor, MultiAuthFactor, }; + +using namespace Dtk::Core; + +const DSysInfo::UosEdition UosEdition = DSysInfo::uosEditionType(); +const bool IsCommunitySystem = (DSysInfo::UosCommunity == UosEdition);//是否是社区版 + +// dconfig 配置名称 +const QString USE_SOLID_BACKGROUND = QStringLiteral("useSolidBackground"); +const QString AUTO_EXIT = QStringLiteral("autoExit"); +const QString HIDE_LOGOUT_BUTTON = QStringLiteral("hideLogoutButton"); +const QString HIDE_ONBOARD = QStringLiteral("hideOnboard"); +const QString ENABLE_ONE_KEY_LOGIN = QStringLiteral("enableOneKeylogin"); +const QString ENABLE_SHORTCUT_FOR_LOCK = QStringLiteral("enableShortcutForLock"); +const QString SHOW_TOP_TIP = QStringLiteral("showTopTip"); +const QString TOP_TIP_TEXT = QStringLiteral("topTipText"); +const QString TOP_TIP_TEXT_FONT = QStringLiteral("topTipTextFont"); +const QString SHOW_USER_NAME = QStringLiteral("showUserName"); +const QString CHANGE_PASSWORD_FOR_NORMAL_USER = QStringLiteral("changePasswordForNormalUser"); +const QString USER_FRAME_MAX_WIDTH = QStringLiteral("userFrameMaxWidth"); +const QString FULL_NAME_FONT = QStringLiteral("fullNameFont"); +const QString LOGIN_PLUGIN_DISPLAY_ORDER = QStringLiteral("loginPluginsDisplayOrder"); +const QString LOGIN_PLUGIN_AUTH_ORDER = QStringLiteral("loginPluginsAuthOrder"); +const QString SHOW_MEDIA_WIDGET = "showMediaWidget"; + +// 系统版本显示配置 +const QString SHOW_SYSTEM_VERSION = QStringLiteral("showSystemVersion"); +// 第三方logo相关配置 +const QString CUSTOM_LOGO_PATH = QStringLiteral("customLogoPath"); +const QString CUSTOM_LOGO_POS = QStringLiteral("customLogoPos"); } diff --git a/src/global_util/dbus/dbuscontrolcenter.cpp b/src/global_util/dbus/dbuscontrolcenter.cpp deleted file mode 100644 index 91101648..00000000 --- a/src/global_util/dbus/dbuscontrolcenter.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusControlCenter -p dbuscontrolcenter com.deepin.dde.ControlCenter.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "dbuscontrolcenter.h" - -/* - * Implementation of interface class DBusControlCenter - */ - -DBusControlCenter::DBusControlCenter(QObject *parent) - : QDBusAbstractInterface("com.deepin.dde.ControlCenter", "/com/deepin/dde/ControlCenter", staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DBusControlCenter::~DBusControlCenter() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - diff --git a/src/global_util/dbus/dbuscontrolcenter.h b/src/global_util/dbus/dbuscontrolcenter.h deleted file mode 100644 index 37c5511b..00000000 --- a/src/global_util/dbus/dbuscontrolcenter.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusControlCenter -p dbuscontrolcenter com.deepin.dde.ControlCenter.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef DBUSCONTROLCENTER_H_1442200179 -#define DBUSCONTROLCENTER_H_1442200179 - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Proxy class for interface com.deepin.dde.ControlCenter - */ -class DBusControlCenter: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.dde.ControlCenter") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach(const QString &prop, keys) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "com.deepin.dde.ControlCenter"; } - -public: - DBusControlCenter(QObject *parent = 0); - - ~DBusControlCenter(); - - Q_PROPERTY(bool ShowInRight READ showInRight NOTIFY ShowInRightChanged) - inline bool showInRight() const - { return qvariant_cast< bool >(property("ShowInRight")); } - - Q_PROPERTY(int X READ x NOTIFY XChanged) - inline int x() const - { return qvariant_cast< int >(property("X")); } - -public Q_SLOTS: // METHODS - inline QDBusPendingReply<> Hide() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Hide"), argumentList); - } - - inline QDBusPendingReply<> HideImmediately() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("HideImmediately"), argumentList); - } - - inline QDBusPendingReply<> Show() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Show"), argumentList); - } - - inline QDBusPendingReply<> ShowImmediately() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ShowImmediately"), argumentList); - } - - inline QDBusPendingReply<> ShowModule(const QString &name) - { - QList argumentList; - argumentList << QVariant::fromValue(name); - return asyncCallWithArgumentList(QStringLiteral("ShowModule"), argumentList); - } - - inline QDBusPendingReply<> Toggle() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Toggle"), argumentList); - } - - inline QDBusPendingReply<> ToggleInLeft() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ToggleInLeft"), argumentList); - } - - inline QDBusPendingReply isNetworkCanShowPassword() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("isNetworkCanShowPassword"), argumentList); - } - -Q_SIGNALS: // SIGNALS -// begin property changed signals -void ShowInRightChanged(); -void XChanged(); -}; - -namespace com { - namespace deepin { - namespace dde { - typedef ::DBusControlCenter ControlCenter; - } - } -} -#endif diff --git a/src/global_util/dbus/dbusdisplaymanager.cpp b/src/global_util/dbus/dbusdisplaymanager.cpp index 98eecd2a..417137a4 100644 --- a/src/global_util/dbus/dbusdisplaymanager.cpp +++ b/src/global_util/dbus/dbusdisplaymanager.cpp @@ -1,38 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusDisplayManager -p dbusdisplaymanager org.freedesktop.DisplayManager.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbusdisplaymanager.h" diff --git a/src/global_util/dbus/dbusdisplaymanager.h b/src/global_util/dbus/dbusdisplaymanager.h index 5b3f5124..f8ec87a6 100644 --- a/src/global_util/dbus/dbusdisplaymanager.h +++ b/src/global_util/dbus/dbusdisplaymanager.h @@ -1,37 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusDisplayManager -p dbusdisplaymanager org.freedesktop.DisplayManager.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSDISPLAYMANAGER_H_1446711552 #define DBUSDISPLAYMANAGER_H_1446711552 diff --git a/src/global_util/dbus/dbushotzone.cpp b/src/global_util/dbus/dbushotzone.cpp index 85d9bfe5..02651da0 100644 --- a/src/global_util/dbus/dbushotzone.cpp +++ b/src/global_util/dbus/dbushotzone.cpp @@ -1,38 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusHotzone -p dbushotzone com.deepin.daemon.Zone.xml - * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbushotzone.h" diff --git a/src/global_util/dbus/dbushotzone.h b/src/global_util/dbus/dbushotzone.h index d5ffb153..af87f687 100644 --- a/src/global_util/dbus/dbushotzone.h +++ b/src/global_util/dbus/dbushotzone.h @@ -1,37 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusHotzone -p dbushotzone com.deepin.daemon.Zone.xml - * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSHOTZONE_H #define DBUSHOTZONE_H @@ -45,6 +14,8 @@ #include #include +#include "dbusconstant.h" + /* * Proxy class for interface com.deepin.daemon.Zone */ @@ -57,7 +28,7 @@ class DBusHotzone: public QDBusAbstractInterface if (3 != arguments.count()) return; QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.Zone") + if (interfaceName != DSS_DBUS::zoneService) return; QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); QStringList keys = changedProps.keys(); @@ -73,7 +44,11 @@ class DBusHotzone: public QDBusAbstractInterface } public: static inline const char *staticInterfaceName() +#ifndef ENABLE_DSS_SNIPE { return "com.deepin.daemon.Zone"; } +#else + { return "org.deepin.dde.Zone1"; } +#endif public: DBusHotzone(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); diff --git a/src/global_util/dbus/dbusinputdevices.cpp b/src/global_util/dbus/dbusinputdevices.cpp deleted file mode 100644 index 49274bea..00000000 --- a/src/global_util/dbus/dbusinputdevices.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p dbusinputdevices -c DBusInputDevices com.deepin.daemon.InputDevices.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "dbusinputdevices.h" - -/* - * Implementation of interface class DBusInputDevices - */ - -QDBusArgument &operator<<(QDBusArgument &argument, const InputDevice &device) -{ - argument.beginStructure(); - argument << device.interface << device.deviceType; - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, InputDevice &device) -{ - argument.beginStructure(); - argument >> device.interface >> device.deviceType; - argument.endStructure(); - return argument; -} - -DBusInputDevices::DBusInputDevices(QObject *parent) - : QDBusAbstractInterface(staticServiceName(), staticObjectPath(), staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DBusInputDevices::~DBusInputDevices() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - diff --git a/src/global_util/dbus/dbusinputdevices.h b/src/global_util/dbus/dbusinputdevices.h deleted file mode 100644 index 7a0993bc..00000000 --- a/src/global_util/dbus/dbusinputdevices.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef DBUSINPUTDEVICES_H_1439802129 -#define DBUSINPUTDEVICES_H_1439802129 - -#include -#include -#include -#include -#include -#include -#include -#include - -struct InputDevice { - QString interface; - QString deviceType; -}; - -typedef QList InputDeviceList; - -Q_DECLARE_METATYPE(InputDevice) -Q_DECLARE_METATYPE(InputDeviceList) - -QDBusArgument &operator<<(QDBusArgument &argument, const InputDevice &device); -const QDBusArgument &operator>>(const QDBusArgument &argument, InputDevice &device); - - -/* - * Proxy class for interface com.deepin.daemon.InputDevices - */ -class DBusInputDevices: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.InputDevices") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach(const QString &prop, keys) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "com.deepin.daemon.InputDevices"; } - static inline const char *staticServiceName() - { return "com.deepin.daemon.InputDevices"; } - static inline const char *staticObjectPath() - { return "/com/deepin/daemon/InputDevices"; } - -public: - DBusInputDevices(QObject *parent = 0); - - ~DBusInputDevices(); - - Q_PROPERTY(InputDeviceList Infos READ infos NOTIFY InfosChanged) - inline InputDeviceList infos() const - { return qvariant_cast< InputDeviceList >(property("Infos")); } - -public Q_SLOTS: // METHODS -Q_SIGNALS: // SIGNALS - // begin property changed signals - void InfosChanged(); -}; - -namespace com { - namespace deepin { - namespace daemon { - typedef ::DBusInputDevices InputDevices; - } - } -} -#endif diff --git a/src/global_util/dbus/dbuskeyboard.cpp b/src/global_util/dbus/dbuskeyboard.cpp deleted file mode 100644 index a94954ba..00000000 --- a/src/global_util/dbus/dbuskeyboard.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p dbuskeyboard -c DBusKeyboard com.deepin.daemon.InputDevice.Keyboard.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "dbuskeyboard.h" - -/* - * Implementation of interface class DBusKeyboard - */ - -DBusKeyboard::DBusKeyboard(QObject *parent) - : QDBusAbstractInterface(staticServiceName(), staticObjectPath(), staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - qDBusRegisterMetaType(); - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DBusKeyboard::~DBusKeyboard() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - diff --git a/src/global_util/dbus/dbuskeyboard.h b/src/global_util/dbus/dbuskeyboard.h deleted file mode 100644 index f1ae0379..00000000 --- a/src/global_util/dbus/dbuskeyboard.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p dbuskeyboard -c DBusKeyboard com.deepin.daemon.InputDevice.Keyboard.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef DBUSKEYBOARD_H_1439802333 -#define DBUSKEYBOARD_H_1439802333 - -#include -#include -#include -#include -#include -#include -#include -#include - -typedef QMap KeyboardLayoutList; - -Q_DECLARE_METATYPE(KeyboardLayoutList) - -/* - * Proxy class for interface com.deepin.daemon.InputDevice.Keyboard - */ -class DBusKeyboard: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.InputDevice.Keyboard") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach(const QString &prop, keys) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "com.deepin.daemon.InputDevice.Keyboard"; } - static inline const char *staticObjectPath() - { return "/com/deepin/daemon/InputDevice/Keyboard"; } - static inline const char *staticServiceName() - { return "com.deepin.daemon.InputDevices"; } - -public: - DBusKeyboard(QObject *parent = 0); - - ~DBusKeyboard(); - - Q_PROPERTY(bool CapslockToggle READ capslockToggle WRITE setCapslockToggle NOTIFY CapslockToggleChanged) - inline bool capslockToggle() const - { return qvariant_cast< bool >(property("CapslockToggle")); } - inline void setCapslockToggle(bool value) - { setProperty("CapslockToggle", QVariant::fromValue(value)); } - - Q_PROPERTY(QString CurrentLayout READ currentLayout WRITE setCurrentLayout NOTIFY CurrentLayoutChanged) - inline QString currentLayout() const - { return qvariant_cast< QString >(property("CurrentLayout")); } - inline void setCurrentLayout(const QString &value) - { setProperty("CurrentLayout", QVariant::fromValue(value)); } - - Q_PROPERTY(int CursorBlink READ cursorBlink WRITE setCursorBlink NOTIFY CursorBlinkChanged) - inline int cursorBlink() const - { return qvariant_cast< int >(property("CursorBlink")); } - inline void setCursorBlink(int value) - { setProperty("CursorBlink", QVariant::fromValue(value)); } - - Q_PROPERTY(uint RepeatDelay READ repeatDelay WRITE setRepeatDelay NOTIFY RepeatDelayChanged) - inline uint repeatDelay() const - { return qvariant_cast< uint >(property("RepeatDelay")); } - inline void setRepeatDelay(uint value) - { setProperty("RepeatDelay", QVariant::fromValue(value)); } - - Q_PROPERTY(bool RepeatEnabled READ repeatEnabled WRITE setRepeatEnabled NOTIFY RepeatEnabledChanged) - inline bool repeatEnabled() const - { return qvariant_cast< bool >(property("RepeatEnabled")); } - inline void setRepeatEnabled(bool value) - { setProperty("RepeatEnabled", QVariant::fromValue(value)); } - - Q_PROPERTY(uint RepeatInterval READ repeatInterval WRITE setRepeatInterval NOTIFY RepeatIntervalChanged) - inline uint repeatInterval() const - { return qvariant_cast< uint >(property("RepeatInterval")); } - inline void setRepeatInterval(uint value) - { setProperty("RepeatInterval", QVariant::fromValue(value)); } - - Q_PROPERTY(QStringList UserLayoutList READ userLayoutList NOTIFY UserLayoutListChanged) - inline QStringList userLayoutList() const - { return qvariant_cast< QStringList >(property("UserLayoutList")); } - - Q_PROPERTY(QStringList UserOptionList READ userOptionList NOTIFY UserOptionListChanged) - inline QStringList userOptionList() const - { return qvariant_cast< QStringList >(property("UserOptionList")); } - -public Q_SLOTS: // METHODS - inline QDBusPendingReply<> AddLayoutOption(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("AddLayoutOption"), argumentList); - } - - inline QDBusPendingReply<> AddUserLayout(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("AddUserLayout"), argumentList); - } - - inline QDBusPendingReply<> ClearLayoutOption() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ClearLayoutOption"), argumentList); - } - - inline QDBusPendingReply<> DeleteLayoutOption(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("DeleteLayoutOption"), argumentList); - } - - inline QDBusPendingReply<> DeleteUserLayout(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("DeleteUserLayout"), argumentList); - } - - inline QDBusPendingReply GetLayoutDesc(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("GetLayoutDesc"), argumentList); - } - - inline QDBusPendingReply LayoutList() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("LayoutList"), argumentList); - } - - inline QDBusPendingReply<> Reset() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Reset"), argumentList); - } - -Q_SIGNALS: // SIGNALS - // begin property changed signals - void CapslockToggleChanged(); - void CurrentLayoutChanged(); - void CursorBlinkChanged(); - void RepeatDelayChanged(); - void RepeatEnabledChanged(); - void RepeatIntervalChanged(); - void UserLayoutListChanged(); - void UserOptionListChanged(); -}; - -namespace com { - namespace deepin { - namespace daemon { - namespace InputDevice { - typedef ::DBusKeyboard Keyboard; - } - } - } -} -#endif diff --git a/src/global_util/dbus/dbuslockfront.cpp b/src/global_util/dbus/dbuslockfront.cpp index afcd3b1e..282a1622 100644 --- a/src/global_util/dbus/dbuslockfront.cpp +++ b/src/global_util/dbus/dbuslockfront.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbuslockfront.h" @@ -30,7 +9,7 @@ */ DBusLockFront::DBusLockFront(QObject *parent) - : QDBusAbstractInterface("com.deepin.dde.lockFront", "/com/deepin/dde/lockFront", staticInterfaceName(), QDBusConnection::sessionBus(), parent) + : QDBusAbstractInterface(DSS_DBUS::lockFrontService, DSS_DBUS::lockFrontPath, staticInterfaceName(), QDBusConnection::sessionBus(), parent) { QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); } diff --git a/src/global_util/dbus/dbuslockfront.h b/src/global_util/dbus/dbuslockfront.h index af1b41a1..3ce75bab 100644 --- a/src/global_util/dbus/dbuslockfront.h +++ b/src/global_util/dbus/dbuslockfront.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSLOCKFRONT_H #define DBUSLOCKFRONT_H @@ -31,6 +10,8 @@ #include #include +#include "dbusconstant.h" + /* * Proxy class for interface com.deepin.dde.lockFront */ @@ -44,7 +25,7 @@ class DBusLockFront: public QDBusAbstractInterface if (3 != arguments.count()) return; QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.dde.lockFront") + if (interfaceName != DSS_DBUS::lockFrontService) return; QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); foreach(const QString &prop, changedProps.keys()) { @@ -59,7 +40,11 @@ class DBusLockFront: public QDBusAbstractInterface } public: static inline const char *staticInterfaceName() +#ifndef ENABLE_DSS_SNIPE { return "com.deepin.dde.lockFront"; } +#else + { return "org.deepin.dde.LockFront1"; } +#endif public: explicit DBusLockFront(QObject *parent = 0); diff --git a/src/global_util/dbus/dbuslockservice.h b/src/global_util/dbus/dbuslockservice.h index 068d1c0e..e25bc360 100644 --- a/src/global_util/dbus/dbuslockservice.h +++ b/src/global_util/dbus/dbuslockservice.h @@ -20,6 +20,8 @@ #include #include +#include "dbusconstant.h" + /* * Proxy class for interface com.deepin.dde.lock */ @@ -28,7 +30,11 @@ class DBusLockService: public QDBusAbstractInterface Q_OBJECT public: static inline const char *staticInterfaceName() +#ifndef ENABLE_DSS_SNIPE { return "com.deepin.dde.LockService"; } +#else + { return "org.deepin.dde.LockService1"; } +#endif enum EventType { PromptQuestion = 1, diff --git a/src/global_util/dbus/dbuslogin1manager.cpp b/src/global_util/dbus/dbuslogin1manager.cpp index c902f791..ecf233b8 100644 --- a/src/global_util/dbus/dbuslogin1manager.cpp +++ b/src/global_util/dbus/dbuslogin1manager.cpp @@ -1,38 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusLogin1Manager -p dbuslogin1manager orgfreedesktop.login1.xml - * - * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbuslogin1manager.h" diff --git a/src/global_util/dbus/dbuslogin1manager.h b/src/global_util/dbus/dbuslogin1manager.h index 22cc2072..4064f1b3 100644 --- a/src/global_util/dbus/dbuslogin1manager.h +++ b/src/global_util/dbus/dbuslogin1manager.h @@ -1,37 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusLogin1Manager -p dbuslogin1manager orgfreedesktop.login1.xml - * - * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSLOGIN1MANAGER_H_1447400884 #define DBUSLOGIN1MANAGER_H_1447400884 diff --git a/src/global_util/dbus/dbusmediaplayer2.cpp b/src/global_util/dbus/dbusmediaplayer2.cpp index b78aabfe..eab8fe90 100644 --- a/src/global_util/dbus/dbusmediaplayer2.cpp +++ b/src/global_util/dbus/dbusmediaplayer2.cpp @@ -1,38 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusMediaPlayer2 -p dbusmediaplayer2 org.mpris.MediaPlayer2.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbusmediaplayer2.h" diff --git a/src/global_util/dbus/dbusmediaplayer2.h b/src/global_util/dbus/dbusmediaplayer2.h index a45bcb10..01f08efa 100644 --- a/src/global_util/dbus/dbusmediaplayer2.h +++ b/src/global_util/dbus/dbusmediaplayer2.h @@ -1,37 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -c DBusMediaPlayer2 -p dbusmediaplayer2 org.mpris.MediaPlayer2.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSMEDIAPLAYER2_H_1446777070 #define DBUSMEDIAPLAYER2_H_1446777070 diff --git a/src/global_util/dbus/dbusvariant.cpp b/src/global_util/dbus/dbusvariant.cpp index 941b433f..328d5964 100644 --- a/src/global_util/dbus/dbusvariant.cpp +++ b/src/global_util/dbus/dbusvariant.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dbusvariant.h" diff --git a/src/global_util/dbus/dbusvariant.h b/src/global_util/dbus/dbusvariant.h index d8a15fcb..daa80c49 100644 --- a/src/global_util/dbus/dbusvariant.h +++ b/src/global_util/dbus/dbusvariant.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DBUSVARIANT #define DBUSVARIANT diff --git a/src/global_util/dbus/displayinterface.cpp b/src/global_util/dbus/displayinterface.cpp deleted file mode 100644 index 23b1c8b8..00000000 --- a/src/global_util/dbus/displayinterface.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p displayinterface -c DisplayInterface com.deepin.daemon.Display.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "displayinterface.h" - -/* - * Implementation of interface class DisplayInterface - */ - -DisplayInterface::DisplayInterface(QObject *parent) - : QDBusAbstractInterface(staticServiceName(), staticObjectPath(), staticInterfaceName(), QDBusConnection::sessionBus(), parent) -{ - qDBusRegisterMetaType(); - qDBusRegisterMetaType(); - - QDBusConnection::sessionBus().connect(this->service(), this->path(), "org.freedesktop.DBus.Properties", "PropertiesChanged","sa{sv}as", this, SLOT(__propertyChanged__(QDBusMessage))); -} - -DisplayInterface::~DisplayInterface() -{ - QDBusConnection::sessionBus().disconnect(service(), path(), "org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", this, SLOT(propertyChanged(QDBusMessage))); -} - - -QDBusArgument &operator<<(QDBusArgument &argument, const DisplayRect &rect) -{ - argument.beginStructure(); - argument << rect.x << rect.y << rect.width << rect.height; - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, DisplayRect &rect) -{ - argument.beginStructure(); - argument >> rect.x >> rect.y >> rect.width >> rect.height; - argument.endStructure(); - return argument; -} - -QDebug operator<<(QDebug deg, const DisplayRect &rect) -{ - qDebug() << "x:" << rect.x << "y:" << rect.y << "width:" << rect.width << "height:" << rect.height; - - return deg; -} diff --git a/src/global_util/dbus/displayinterface.h b/src/global_util/dbus/displayinterface.h deleted file mode 100644 index cc353e99..00000000 --- a/src/global_util/dbus/displayinterface.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p displayinterface -c DisplayInterface com.deepin.daemon.Display.xml - * - * qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef DISPLAYINTERFACE_H_1439948860 -#define DISPLAYINTERFACE_H_1439948860 - -#include -#include -#include -#include -#include -#include -#include -#include - -typedef QMap BrightnessMap; - -Q_DECLARE_METATYPE(BrightnessMap) - -struct DisplayRect{ - qint16 x; - qint16 y; - quint16 width; - quint16 height; - - operator QRect() const - { - return QRect(x, y, width, height); - } -}; - -Q_DECLARE_METATYPE(DisplayRect) - -QDBusArgument &operator<<(QDBusArgument &argument, const DisplayRect &rect); -const QDBusArgument &operator>>(const QDBusArgument &argument, DisplayRect &rect); -QDebug operator<<(QDebug deg, const DisplayRect &rect); - -/* - * Proxy class for interface com.deepin.daemon.Display - */ -class DisplayInterface: public QDBusAbstractInterface -{ - Q_OBJECT - - Q_SLOT void __propertyChanged__(const QDBusMessage& msg) - { - QList arguments = msg.arguments(); - if (3 != arguments.count()) - return; - QString interfaceName = msg.arguments().at(0).toString(); - if (interfaceName !="com.deepin.daemon.Display") - return; - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - QStringList keys = changedProps.keys(); - foreach(const QString &prop, keys) { - const QMetaObject* self = metaObject(); - for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) { - QMetaProperty p = self->property(i); - if (p.name() == prop) { - Q_EMIT p.notifySignal().invoke(this); - } - } - } - } -public: - static inline const char *staticInterfaceName() - { return "com.deepin.daemon.Display"; } - static inline const char *staticServiceName() - { return "com.deepin.daemon.Display"; } - static inline const char *staticObjectPath() - { return "/com/deepin/daemon/Display"; } - -public: - DisplayInterface(QObject *parent = 0); - - ~DisplayInterface(); - - Q_PROPERTY(BrightnessMap Brightness READ brightness NOTIFY BrightnessChanged) - inline BrightnessMap brightness() const - { return qvariant_cast< BrightnessMap >(property("Brightness")); } - - Q_PROPERTY(QDBusObjectPath BuiltinOutput READ builtinOutput NOTIFY BuiltinOutputChanged) - inline QDBusObjectPath builtinOutput() const - { return qvariant_cast< QDBusObjectPath >(property("BuiltinOutput")); } - - Q_PROPERTY(short DisplayMode READ displayMode NOTIFY DisplayModeChanged) - inline short displayMode() const - { return qvariant_cast< short >(property("DisplayMode")); } - - Q_PROPERTY(bool HasChanged READ hasChanged NOTIFY HasChangedChanged) - inline bool hasChanged() const - { return qvariant_cast< bool >(property("HasChanged")); } - - Q_PROPERTY(QList Monitors READ monitors NOTIFY MonitorsChanged) - inline QList monitors() const - { return qvariant_cast< QList >(property("Monitors")); } - - Q_PROPERTY(QString Primary READ primary NOTIFY PrimaryChanged) - inline QString primary() const - { return qvariant_cast< QString >(property("Primary")); } - - Q_PROPERTY(DisplayRect PrimaryRect READ primaryRect NOTIFY PrimaryRectChanged) - inline DisplayRect primaryRect() const - { return qvariant_cast< DisplayRect >(property("PrimaryRect")); } - - Q_PROPERTY(ushort ScreenHeight READ screenHeight NOTIFY ScreenHeightChanged) - inline ushort screenHeight() const - { return qvariant_cast< ushort >(property("ScreenHeight")); } - - Q_PROPERTY(ushort ScreenWidth READ screenWidth NOTIFY ScreenWidthChanged) - inline ushort screenWidth() const - { return qvariant_cast< ushort >(property("ScreenWidth")); } - -public Q_SLOTS: // METHODS - inline QDBusPendingReply<> Apply() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Apply"), argumentList); - } - - inline QDBusPendingReply<> AssociateTouchScreen(const QString &in0, const QString &in1) - { - QList argumentList; - argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); - return asyncCallWithArgumentList(QStringLiteral("AssociateTouchScreen"), argumentList); - } - - inline QDBusPendingReply<> ChangeBrightness(const QString &in0, double in1) - { - QList argumentList; - argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); - return asyncCallWithArgumentList(QStringLiteral("ChangeBrightness"), argumentList); - } - - inline QDBusPendingReply<> JoinMonitor(const QString &in0, const QString &in1) - { - QList argumentList; - argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); - return asyncCallWithArgumentList(QStringLiteral("JoinMonitor"), argumentList); - } - - inline QDBusPendingReply ListOutputNames() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ListOutputNames"), argumentList); - } - - inline QDBusPendingReply QueryCurrentPlanName() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("QueryCurrentPlanName"), argumentList); - } - - inline QDBusPendingReply QueryOutputFeature(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("QueryOutputFeature"), argumentList); - } - - inline QDBusPendingReply<> Reset() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Reset"), argumentList); - } - - inline QDBusPendingReply<> ResetBrightness(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("ResetBrightness"), argumentList); - } - - inline QDBusPendingReply<> ResetChanges() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("ResetChanges"), argumentList); - } - - inline QDBusPendingReply<> SaveChanges() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("SaveChanges"), argumentList); - } - - inline QDBusPendingReply<> SetBrightness(const QString &in0, double in1) - { - QList argumentList; - argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); - return asyncCallWithArgumentList(QStringLiteral("SetBrightness"), argumentList); - } - - inline QDBusPendingReply<> SetPrimary(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("SetPrimary"), argumentList); - } - - inline QDBusPendingReply<> SplitMonitor(const QString &in0) - { - QList argumentList; - argumentList << QVariant::fromValue(in0); - return asyncCallWithArgumentList(QStringLiteral("SplitMonitor"), argumentList); - } - - inline QDBusPendingReply<> SwitchMode(short in0, const QString &in1) - { - QList argumentList; - argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); - return asyncCallWithArgumentList(QStringLiteral("SwitchMode"), argumentList); - } - -Q_SIGNALS: // SIGNALS - //void PrimaryChanged(const QRect &in0); -// begin property changed signals -void BrightnessChanged(); -void BuiltinOutputChanged(); -void DisplayModeChanged(); -void HasChangedChanged(); -void MonitorsChanged(); -void PrimaryChanged(); -void PrimaryRectChanged(); -void ScreenHeightChanged(); -void ScreenWidthChanged(); -}; - -#endif diff --git a/src/global_util/dbus/types/arrayint.cpp b/src/global_util/dbus/types/arrayint.cpp new file mode 100644 index 00000000..e502b262 --- /dev/null +++ b/src/global_util/dbus/types/arrayint.cpp @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "arrayint.h" + +void registerArrayIntMetaType() +{ + qRegisterMetaType("ArrayInt"); + qDBusRegisterMetaType(); +} diff --git a/src/global_util/dbus/types/arrayint.h b/src/global_util/dbus/types/arrayint.h new file mode 100644 index 00000000..b303d94d --- /dev/null +++ b/src/global_util/dbus/types/arrayint.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ARRAYINT_H +#define ARRAYINT_H + +#include + +using ArrayInt = QList; +Q_DECLARE_METATYPE(ArrayInt); + +void registerArrayIntMetaType(); + +#endif // ARRAYINT_H diff --git a/src/global_util/dbus/types/mfainfolist.cpp b/src/global_util/dbus/types/mfainfolist.cpp new file mode 100644 index 00000000..1ed41d00 --- /dev/null +++ b/src/global_util/dbus/types/mfainfolist.cpp @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "mfainfolist.h" + +bool MFAInfo::operator==(const MFAInfo &info) const +{ + return AuthType == info.AuthType && Priority == info.Priority + && InputType == info.InputType && Required == info.Required; +} + +QDebug operator<<(QDebug argument, const MFAInfo &info) +{ + argument << info.AuthType << "," << info.Priority << "," << info.InputType << "," << info.Required; + return argument; +} + +QDBusArgument &operator<<(QDBusArgument &argument, const MFAInfo &info) +{ + argument.beginStructure(); + argument << info.AuthType << info.Priority << info.InputType << info.Required; + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, MFAInfo &info) +{ + argument.beginStructure(); + argument >> info.AuthType >> info.Priority >> info.InputType >> info.Required; + argument.endStructure(); + return argument; +} + +void registerMFAInfoMetaType() +{ + qRegisterMetaType("MFAInfo"); + qDBusRegisterMetaType(); +} + +void registerMFAInfoListMetaType() +{ + registerMFAInfoMetaType(); + qRegisterMetaType("MFAInfoList"); + qDBusRegisterMetaType(); +} diff --git a/src/global_util/dbus/types/mfainfolist.h b/src/global_util/dbus/types/mfainfolist.h new file mode 100644 index 00000000..99104017 --- /dev/null +++ b/src/global_util/dbus/types/mfainfolist.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef MFAINFO_H +#define MFAINFO_H + +#include +#include + +struct MFAInfo { + int AuthType; + int Priority; + int InputType; + bool Required; + + bool operator==(const MFAInfo &info) const; +}; + +Q_DECLARE_METATYPE(MFAInfo); +typedef QList MFAInfoList; +Q_DECLARE_METATYPE(MFAInfoList); + +QDebug operator<<(QDebug argument, const MFAInfo &info); +QDBusArgument &operator<<(QDBusArgument &argument, const MFAInfo &info); +const QDBusArgument &operator>>(const QDBusArgument &argument, MFAInfo &info); + +void registerMFAInfoListMetaType(); + +#endif // MFAINFO_H diff --git a/src/global_util/dbusconstant.h b/src/global_util/dbusconstant.h new file mode 100644 index 00000000..6dc1912e --- /dev/null +++ b/src/global_util/dbusconstant.h @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: 2015 - 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DBUSCONSTANT_H +#define DBUSCONSTANT_H + +#include + +namespace DSS_DBUS { + +#ifndef ENABLE_DSS_SNIPE + const QString accountsService = "com.deepin.daemon.Accounts"; + const QString accountsPath = "/com/deepin/daemon/Accounts"; + const QString accountsUserPath = "/com/deepin/daemon/Accounts/User%1"; + const QString accountsUserInterface = "com.deepin.daemon.Accounts.User"; + const QString loginedPath = "/com/deepin/daemon/Logined"; + const QString powerService = "com.deepin.system.Power"; + const QString powerPath = "/com/deepin/system/Power"; + const QString sessionPowerService = "com.deepin.daemon.Power"; + const QString sessionPowerPath = "/com/deepin/daemon/Power"; + const QString lastoreService = "com.deepin.lastore"; + const QString lastorePath = "/com/deepin/lastore"; + const QString lastoreInterface = "com.deepin.lastore.Manager"; + const QString lockFrontService = "com.deepin.dde.lockFront"; + const QString lockFrontPath = "/com/deepin/dde/lockFront"; + const QString shutdownService = "com.deepin.dde.shutdownFront"; + const QString shutdownPath = "/com/deepin/dde/shutdownFront"; + const QString systemDisplayService = "com.deepin.system.Display"; + const QString systemDisplayPath = "/com/deepin/system/Display"; + const QString inhibitHintService = "com.deepin.InhibitHint"; + const QString inhibitHintPath = "/com/deepin/InhibitHint"; + const QString imageEffectService = "com.deepin.daemon.ImageEffect"; + const QString imageEffectPath = "/com/deepin/daemon/ImageEffect"; + const QString lockService = "com.deepin.dde.LockService"; + const QString lockServicePath = "/com/deepin/dde/LockService"; + const QString zoneService = "com.deepin.daemon.Zone"; + const QString zonePath = "/com/deepin/daemon/Zone"; + const QString sessionManagerService = "com.deepin.SessionManager"; + const QString sessionManagerPath = "/com/deepin/SessionManager"; + const QString authenticateService = "com.deepin.daemon.Authenticate"; + const QString authenticatePath = "/com/deepin/daemon/Authenticate"; + const QString fingerprintAuthPath = "/com/deepin/daemon/Authenticate/Fingerprint"; + const QString fingerprintAuthInterface = "com.deepin.daemon.Authenticate.Fingerprint"; + const QString udcpIamService = "com.deepin.udcp.iam"; + const QString udcpIamPath = "/com/deepin/udcp/iam"; + const QString controlCenterService = "com.deepin.dde.ControlCenter"; + const QString controlCenterPath = "/com/deepin/daemon/ControlCenter"; + const QString systemDaemonService = "com.deepin.daemon.Daemon"; + const QString systemDaemonPath = "/com/deepin/daemon/Daemon"; + const QString systemInfoService = "com.deepin.daemon.SystemInfo"; + const QString systemInfoPath = "/com/deepin/daemon/SystemInfo"; + const QString keybindingService = "com.deepin.daemon.Keybinding"; + const QString keybindingPath = "/com/deepin/daemon/Keybinding"; + const QString screenSaveService = "com.deepin.daemon.ScreenSaver"; + +#else + const QString accountsService = "org.deepin.dde.Accounts1"; + const QString accountsPath = "/org/deepin/dde/Accounts1"; + const QString accountsUserPath = "/org/deepin/dde/Accounts1/User%1"; + const QString accountsUserInterface = "org.deepin.dde.Accounts1.User"; + const QString loginedPath = "/org/deepin/dde/Logined"; + const QString powerService = "org.deepin.dde.Power1"; + const QString powerPath = "/org/deepin/dde/Power1"; + const QString sessionPowerService = "org.deepin.dde.Power1"; + const QString sessionPowerPath = "/org/deepin/dde/Power1"; + const QString lastoreService = "org.deepin.dde.Lastore1"; + const QString lastorePath = "/org/deepin/dde/Lastore1"; + const QString lastoreInterface = "org.deepin.dde.Lastore1.Manager"; + const QString lockFrontService = "org.deepin.dde.LockFront1"; + const QString lockFrontPath = "/org/deepin/dde/LockFront1"; + const QString shutdownService = "org.deepin.dde.ShutdownFront1"; + const QString shutdownPath = "/org/deepin/dde/ShutdownFront1"; + const QString systemDisplayService = "org.deepin.dde.Display1"; + const QString systemDisplayPath = "/org/deepin/dde/Display1"; + const QString inhibitHintService = "org.deepin.dde.InhibitHint1"; + const QString inhibitHintPath = "/org/deepin/dde/InhibitHint1"; + const QString imageEffectService = "org.deepin.dde.ImageEffect1"; + const QString imageEffectPath = "/org/deepin/dde/ImageEffect1"; + const QString lockService = "org.deepin.dde.LockService1"; + const QString lockServicePath = "/org/deepin/dde/LockService1"; + const QString zoneService = "org.deepin.dde.Zone1"; + const QString zonePath = "/org/deepin/dde/Zone1"; + const QString sessionManagerService = "org.deepin.dde.SessionManager1"; + const QString sessionManagerPath = "/org/deepin/dde/SessionManager1"; + const QString authenticateService = "org.deepin.dde.Authenticate1"; + const QString authenticatePath = "/org/deepin/dde/Authenticate1"; + const QString fingerprintAuthPath = "/org/deepin/dde/Authenticate1/Fingerprint"; + const QString fingerprintAuthInterface = "org.deepin.dde.Authenticate1.Fingerprint"; + // TODO udcp path + const QString udcpIamService = "com.deepin.udcp.iam"; + const QString udcpIamPath = "/com/deepin/udcp/iam"; + const QString controlCenterService = "org.deepin.dde.ControlCenter1"; + const QString controlCenterPath = "/org/deepin/dde/ControlCenter1"; + const QString systemDaemonService = "org.deepin.dde.Daemon1"; + const QString systemDaemonPath = "/org/deepin/dde/Daemon1"; + const QString systemInfoService = "org.deepin.dde.SystemInfo1"; + const QString systemInfoPath = "/org/deepin/dde/SystemInfo1"; + const QString keybindingService = "org.deepin.dde.Keybinding1"; + const QString keybindingPath = "/org/deepin/dde/Keybinding1"; + const QString screenSaveService = "org.freedesktop.ScreenSaver"; + +#endif +} + +#endif //DBUSCONSTANT_H diff --git a/src/global_util/dconfig_helper.cpp b/src/global_util/dconfig_helper.cpp new file mode 100644 index 00000000..f1836a50 --- /dev/null +++ b/src/global_util/dconfig_helper.cpp @@ -0,0 +1,219 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dconfig_helper.h" + +#include "public_func.h" + +#include + +#include + +DCORE_USE_NAMESPACE + +Q_GLOBAL_STATIC(DConfigHelper, dConfigWatcher) + +DConfigHelper::DConfigHelper(QObject *parent) + : QObject(parent) +{ + moveToThread(qApp->thread()); + initializeDConfig(getDefaultConfigFileName(), getDefaultConfigFileName(), ""); +} + +DConfigHelper *DConfigHelper::instance() +{ + return dConfigWatcher; +} + +DConfig *DConfigHelper::initializeDConfig(const QString &appId, + const QString &name, + const QString &subpath) +{ + QMutexLocker locker(&m_mutex); + DConfig *dConfig = DConfig::create(appId, name, subpath); + if (!dConfig) { + qCWarning(DDE_SHELL) << "Create DConfig failed, appId: " << appId << ", name: " << name + << ", subpath: " << subpath; + return nullptr; + } + + m_dConfigs[packageDConfigPath(appId, name, subpath)] = dConfig; + m_bindInfos[dConfig] = {}; + + dConfig->moveToThread(qApp->thread()); + dConfig->setParent(this); + + // 即时响应数据变化 + connect(dConfig, &DConfig::valueChanged, this, [this, dConfig](const QString &key) { + const QVariant &value = dConfig->value(key); + auto it = m_bindInfos.find(dConfig); + if (it == m_bindInfos.end()) + return; + + auto itBindInfo = it.value().begin(); + for (; itBindInfo != it.value().end(); ++itBindInfo) { + if (itBindInfo.value().contains(key)) { + auto callbackIt = m_objCallbackMap.find(itBindInfo.key()); + if (callbackIt != m_objCallbackMap.end()) + callbackIt.value()(key, value, itBindInfo.key()); + } + } + }); + + return dConfig; +} + +void DConfigHelper::bind(QObject *obj, const QString &key, OnPropertyChangedCallback callback) +{ + bind(getDefaultConfigFileName(), getDefaultConfigFileName(), "", obj, key, callback); +} + +void DConfigHelper::bind(const QString &appId, + const QString &name, + const QString &subpath, + QObject *obj, + const QString &key, + OnPropertyChangedCallback callback) +{ + if (!obj) + return; + + DConfig *dConfig = dConfigObject(appId, name, subpath); + if (!dConfig) { + qCWarning(DDE_SHELL) << "DConfig is nullptr"; + return; + } + + auto it = m_bindInfos.find(dConfig); + if (it == m_bindInfos.end()) { + qCWarning(DDE_SHELL) << "Can not find bind info"; + return; + } + + QMap &bindInfo = it.value(); + auto bindInfoIt = bindInfo.find(obj); + if (bindInfoIt != bindInfo.end()) { + if (!bindInfoIt.value().contains(key)) + bindInfoIt.value().append(key); + } else { + bindInfo[obj] = QStringList(key); + } + + m_objCallbackMap.insert(obj, callback); + connect(obj, &QObject::destroyed, this, [this, obj] { + unBind(obj); + }); +} + +DConfig *DConfigHelper::defaultDConfigObject() +{ + return dConfigObject(getDefaultConfigFileName(), getDefaultConfigFileName(), ""); +} + +void DConfigHelper::unBind(QObject *obj, const QString &key) +{ + qCInfo(DDE_SHELL) << "Unbind, obj: " << obj << ", key: " << key; + if (!obj) { + qCWarning(DDE_SHELL) << "Unbinding object is null"; + return; + } + + bool objStillUseful = false; + auto it = m_bindInfos.begin(); + for (; it != m_bindInfos.end(); ++it) { + if (key.isEmpty()) { + it->remove(obj); + } else { + // 移除key,移除完如果obj没有绑定了key了,那么把obj也移除掉 + auto it1 = it.value().find(obj); + if (it1 != it.value().end()) { + it1.value().removeAll(key); + if (it1.value().isEmpty()) { + it->remove(obj); + } else { + objStillUseful = true; + } + } + } + } + + if (key.isEmpty() || !objStillUseful) + m_objCallbackMap.remove(obj); +} + +/** + * @brief Get config from default dconfig + */ +QVariant DConfigHelper::getConfig(const QString &key, const QVariant &defaultValue) +{ + return getConfig(getDefaultConfigFileName(), getDefaultConfigFileName(), "", key, defaultValue); +} + +/** + * @brief Set config to default dconfig + */ +void DConfigHelper::setConfig(const QString &key, const QVariant &value) +{ + return setConfig(getDefaultConfigFileName(), getDefaultConfigFileName(), "", key, value); +} + +QVariant DConfigHelper::getConfig(const QString &appId, + const QString &name, + const QString &subpath, + const QString &key, + const QVariant &defaultValue) +{ + DConfig *dConfig = dConfigObject(appId, name, subpath); + if (!dConfig) { + qCWarning(DDE_SHELL) << "DConfig object is null"; + return defaultValue; + } + + if (!dConfig->keyList().contains(key)) + return defaultValue; + + const QVariant &value = dConfig->value(key); + return value; +} + +void DConfigHelper::setConfig(const QString &appId, + const QString &name, + const QString &subpath, + const QString &key, + const QVariant &value) +{ + DConfig *dConfig = dConfigObject(appId, name, subpath); + if (!dConfig) { + qCWarning(DDE_SHELL) << "DConfig object is null"; + return; + } + + if (!dConfig->keyList().contains(key)) { + qCWarning(DDE_SHELL) << "DConfig does not contain key: " << key; + return; + } + + dConfig->setValue(key, value); +} + +DConfig *DConfigHelper::dConfigObject(const QString &appId, + const QString &name, + const QString &subpath) +{ + const QString &configPath = packageDConfigPath(appId, name, subpath); + DConfig *dConfig = nullptr; + if (m_dConfigs.contains(configPath)) + dConfig = m_dConfigs.value(configPath); + else + dConfig = initializeDConfig(appId, name, subpath); + + return dConfig; +} + +QString DConfigHelper::packageDConfigPath(const QString &appId, + const QString &name, + const QString &subpath) const +{ + return appId + name + subpath; +} diff --git a/src/global_util/dconfig_helper.h b/src/global_util/dconfig_helper.h new file mode 100644 index 00000000..1cfb7de6 --- /dev/null +++ b/src/global_util/dconfig_helper.h @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include +#include +#include + +using OnPropertyChangedCallback = void (*)(const QString &, const QVariant &, QObject *); + +/** + * @brief 配置变化回调函数 + * + * @param key 配置键值 + * @param value 配置值 + */ +using OnPropertiesChanged = void (*)(const QString &key, const QVariant &value); + +class DConfigHelper : public QObject +{ + Q_OBJECT +public: + explicit DConfigHelper(QObject *parent = nullptr); + static DConfigHelper *instance(); + + // 注意:多个配置文件区分同名的key + void bind(QObject *obj, const QString &key, OnPropertyChangedCallback callback); + void bind(const QString &appId, + const QString &name, + const QString &subpath, + QObject *obj, + const QString &key, + OnPropertyChangedCallback callback); + void unBind(QObject *obj, const QString &key = ""); + + QVariant getConfig(const QString &appId, + const QString &name, + const QString &subpath, + const QString &key, + const QVariant &defaultValue); + QVariant getConfig(const QString &key, const QVariant &defaultValue); + + void setConfig(const QString &appId, + const QString &name, + const QString &subpath, + const QString &key, + const QVariant &value); + void setConfig(const QString &key, const QVariant &value); + +private: + Q_DISABLE_COPY(DConfigHelper) + + Dtk::Core::DConfig *initializeDConfig(const QString &appId, + const QString &name, + const QString &subpath); + Dtk::Core::DConfig *dConfigObject(const QString &appId, + const QString &name, + const QString &subpath); + Dtk::Core::DConfig *defaultDConfigObject(); + QString packageDConfigPath(const QString &appId, + const QString &name, + const QString &subpath) const; + +private: + QMutex m_mutex; + QMap m_dConfigs; + QMap> m_bindInfos; + QMap m_objCallbackMap; +}; diff --git a/src/global_util/dconfigwatcher.cpp b/src/global_util/dconfigwatcher.cpp new file mode 100644 index 00000000..51d50e0c --- /dev/null +++ b/src/global_util/dconfigwatcher.cpp @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2020 - 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dconfigwatcher.h" + +#include +#include + +DConfigWatcher::DConfigWatcher(QObject *parent) + : QObject(parent) + , m_dConfig(Dtk::Core::DConfig::create("org.deepin.dde.session-shell", "org.deepin.dde.session-shell", QString(), this)) +{ + connect(m_dConfig, &Dtk::Core::DConfig::valueChanged, this, &DConfigWatcher::onStatusModeChanged); +} + +DConfigWatcher *DConfigWatcher::instance() +{ + static DConfigWatcher w; + return &w; +} + +void DConfigWatcher::bind(const QString &key, QWidget *binder) +{ + m_map.insert(key, binder); + + setStatus(key, binder); +} + +void DConfigWatcher::erase(const QString &key) +{ + if (m_map.isEmpty() || !m_map.contains(key)) + return; + + m_map.remove(key); +} + +void DConfigWatcher::erase(const QString &key, QWidget *binder) +{ + if (m_map.isEmpty() || !m_map.contains(key)) + return; + + m_map.remove(key, binder); +} + +void DConfigWatcher::setStatus(const QString &key, QWidget *binder) +{ + if (!binder) + return; + + const int setting = m_dConfig->value(key).toInt(); + if (setting == Status_Enabled) { + binder->setEnabled(true); + } else if (setting == Status_Disabled) { + binder->setEnabled(false); + } + + binder->setVisible(setting != Status_Hidden); +} + +const int DConfigWatcher::getStatus(const QString &key) +{ + return m_dConfig->value(key).toInt(); +} + +void DConfigWatcher::onStatusModeChanged(const QString &key) +{ + if (m_map.isEmpty() || !m_map.contains(key)) + return; + + // 重新设置控件对应的显示类型 + for (auto mapUnit = m_map.begin(); mapUnit != m_map.end(); ++mapUnit) { + if (key == mapUnit.key()) { + setStatus(key, mapUnit.value()); + emit enableChanged(key, mapUnit.value()->isEnabled()); + } + } +} diff --git a/src/global_util/dconfigwatcher.h b/src/global_util/dconfigwatcher.h new file mode 100644 index 00000000..50f5bc20 --- /dev/null +++ b/src/global_util/dconfigwatcher.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2020 - 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DCONFIGWATCHER_H +#define DCONFIGWATCHER_H + +#include + +const static int Status_Enabled = 0; +const static int Status_Disabled = 1; +const static int Status_Hidden = 2; + +class DConfigWatcher : public QObject +{ + Q_OBJECT +public: + static DConfigWatcher *instance(); + + void bind(const QString &key, QWidget *binder); + void erase(const QString &key); + void erase(const QString &key, QWidget *binder); + const int getStatus(const QString &key); + +signals: + void enableChanged(const QString &key, bool enable); + +private: + DConfigWatcher(QObject *parent = nullptr); + + void setStatus(const QString &key, QWidget *binder); + void onStatusModeChanged(const QString &key); + +private: + QMultiHash m_map; + Dtk::Core::DConfig *m_dConfig = nullptr; +}; + +#endif // DCONFIGWATCHER_H diff --git a/src/global_util/gsettingwatcher.cpp b/src/global_util/gsettingwatcher.cpp index 99bf11b9..20daf88c 100644 --- a/src/global_util/gsettingwatcher.cpp +++ b/src/global_util/gsettingwatcher.cpp @@ -1,24 +1,8 @@ -/* - * Copyright (C) 2020 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: xuyanghe - * - * Maintainer: xuyanghe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef ENABLE_DSS_SNIPE #include "gsettingwatcher.h" #include @@ -121,3 +105,5 @@ void GSettingWatcher::onStatusModeChanged(const QString &key) } } } + +#endif // ENABLE_DSS_SNIPE \ No newline at end of file diff --git a/src/global_util/gsettingwatcher.h b/src/global_util/gsettingwatcher.h index 93860ddb..51392906 100644 --- a/src/global_util/gsettingwatcher.h +++ b/src/global_util/gsettingwatcher.h @@ -1,23 +1,8 @@ -/* - * Copyright (C) 2020 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: xuyanghe - * - * Maintainer: xuyanghe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ENABLE_DSS_SNIPE #ifndef GSETTINGWATCHER_H #define GSETTINGWATCHER_H @@ -52,3 +37,5 @@ class GSettingWatcher : public QObject }; #endif // GSETTINGWATCHER_H + +#endif // ENABLE_DSS_SNIPE diff --git a/src/global_util/keyboardmonitor/keyboardmonitor.cpp b/src/global_util/keyboardmonitor/keyboardmonitor.cpp index 37ef25aa..44196bd7 100644 --- a/src/global_util/keyboardmonitor/keyboardmonitor.cpp +++ b/src/global_util/keyboardmonitor/keyboardmonitor.cpp @@ -1,44 +1,34 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * zorowk - * - * Maintainer: sbw - * kirigaya - * Hualet - * zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "keyboardmonitor.h" + #include +#include + DGUI_USE_NAMESPACE -KeyboardMonitor::KeyboardMonitor() : QThread() +KeyboardMonitor::KeyboardMonitor() + : QThread() + , m_keyBoardPlatform(nullptr) { if (DGuiApplicationHelper::isXWindowPlatform()) { - keyBoardPlatform = new KeyboardPlantformX11(); + m_keyBoardPlatform = new KeyboardPlatformX11(); } else { - keyBoardPlatform = new KeyboardPlantformWayland(); +#ifdef USE_DEEPIN_WAYLAND + m_keyBoardPlatform = new KeyboardPlatformWayland(); +#endif + } + + if (m_keyBoardPlatform) { + connect(m_keyBoardPlatform, &KeyBoardPlatform::capsLockStatusChanged, this, &KeyboardMonitor::capsLockStatusChanged); + connect(m_keyBoardPlatform, &KeyBoardPlatform::numLockStatusChanged, this, &KeyboardMonitor::numLockStatusChanged); + connect(m_keyBoardPlatform, &KeyBoardPlatform::initialized, this, &KeyboardMonitor::initialized); } - connect(keyBoardPlatform, &KeyBoardPlatform::capslockStatusChanged, this, &KeyboardMonitor::capslockStatusChanged); - connect(keyBoardPlatform, &KeyBoardPlatform::numlockStatusChanged, this, &KeyboardMonitor::numlockStatusChanged); + + start(QThread::LowestPriority); } KeyboardMonitor *KeyboardMonitor::instance() @@ -52,22 +42,44 @@ KeyboardMonitor *KeyboardMonitor::instance() return KeyboardMonitorInstance; } -bool KeyboardMonitor::isCapslockOn() +bool KeyboardMonitor::isCapsLockOn() { - return keyBoardPlatform->isCapslockOn(); + if (!m_keyBoardPlatform) + return false; + + return m_keyBoardPlatform->isCapsLockOn(); } -bool KeyboardMonitor::isNumlockOn() +bool KeyboardMonitor::isNumLockOn() { - return keyBoardPlatform->isNumlockOn(); + if (!m_keyBoardPlatform) + return false; + + return m_keyBoardPlatform->isNumLockOn(); } -bool KeyboardMonitor::setNumlockStatus(const bool &on) +bool KeyboardMonitor::setNumLockStatus(const bool &on) { - return keyBoardPlatform->setNumlockStatus(on); + if (!m_keyBoardPlatform) + return false; + + return m_keyBoardPlatform->setNumLockStatus(on); } void KeyboardMonitor::run() { - keyBoardPlatform->run(); + if (!m_keyBoardPlatform) + return; + + m_keyBoardPlatform->run(); } + +void KeyboardMonitor::ungrabKeyboard() +{ + if (!m_keyBoardPlatform) + return; + + if (!(QFile::exists(DPMS_STATE_FILE) && QFile(DPMS_STATE_FILE).readAll() == "1")) { + m_keyBoardPlatform->ungrabKeyboard(); + } +} \ No newline at end of file diff --git a/src/global_util/keyboardmonitor/keyboardmonitor.h b/src/global_util/keyboardmonitor/keyboardmonitor.h index 5edae6f0..b6f3cd34 100644 --- a/src/global_util/keyboardmonitor/keyboardmonitor.h +++ b/src/global_util/keyboardmonitor/keyboardmonitor.h @@ -1,36 +1,17 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * zorowk - * - * Maintainer: sbw - * kirigaya - * Hualet - * zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef KEYBOARDMONITOR_H #define KEYBOARDMONITOR_H #include #include "keyboardplantform_x11.h" +#ifdef USE_DEEPIN_WAYLAND #include "keyboardplantform_wayland.h" +#endif + +#define DPMS_STATE_FILE "/tmp/dpms-state" //black screen state;bug:222049 class KeyboardMonitor : public QThread { @@ -38,20 +19,22 @@ class KeyboardMonitor : public QThread public: static KeyboardMonitor *instance(); - bool isCapslockOn(); - bool isNumlockOn(); - bool setNumlockStatus(const bool &on); + bool isCapsLockOn(); + bool isNumLockOn(); + bool setNumLockStatus(const bool &on); + void ungrabKeyboard(); signals: - void capslockStatusChanged(bool on); - void numlockStatusChanged(bool on); + void capsLockStatusChanged(bool on); + void numLockStatusChanged(bool on); + void initialized(); protected: void run() Q_DECL_OVERRIDE; private: KeyboardMonitor(); - KeyBoardPlatform* keyBoardPlatform = nullptr; + KeyBoardPlatform* m_keyBoardPlatform; }; #endif // KEYBOARDMONITOR_H diff --git a/src/global_util/keyboardmonitor/keyboardplantform_wayland.cpp b/src/global_util/keyboardmonitor/keyboardplantform_wayland.cpp index df743c85..2be2cc9a 100644 --- a/src/global_util/keyboardmonitor/keyboardplantform_wayland.cpp +++ b/src/global_util/keyboardmonitor/keyboardplantform_wayland.cpp @@ -1,55 +1,170 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifdef USE_DEEPIN_WAYLAND #include "keyboardplantform_wayland.h" +#include "constants.h" -#include -#include +#include -KeyboardPlantformWayland::KeyboardPlantformWayland(QObject *parent) +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +KeyboardPlatformWayland::KeyboardPlatformWayland(QObject *parent) : KeyBoardPlatform(parent) + , m_connectionThread(new QThread(this)) + , m_connectionThreadObject(new ConnectionThread()) + , m_ddeKeyboard(nullptr) + , m_fakeInput(nullptr) + , m_ddeSeat(nullptr) + , m_eventQueue(nullptr) + , m_capsLock(false) + , m_numLockOn(false) + , m_repeatTimer(new QTimer(this)) { + initStatus(); + m_repeatTimer->setInterval(100); + m_repeatTimer->setSingleShot(true); } -bool KeyboardPlantformWayland::isCapslockOn() +KeyboardPlatformWayland::~KeyboardPlatformWayland() { - return false; + m_connectionThread->quit(); + m_connectionThread->wait(); + m_connectionThreadObject->deleteLater(); } -bool KeyboardPlantformWayland::isNumlockOn() +bool KeyboardPlatformWayland::isCapsLockOn() { - return false; + return m_capsLock; +} + +bool KeyboardPlatformWayland::isNumLockOn() +{ + return m_numLockOn; } -bool KeyboardPlantformWayland::setNumlockStatus(const bool &on) +bool KeyboardPlatformWayland::setNumLockStatus(const bool &on) { - Q_UNUSED(on); + qDebug() << "Set num lock state: " << on << ", numlockon: " << m_numLockOn; + if (m_fakeInput && m_fakeInput->isValid() && on != m_numLockOn) { + m_fakeInput->authenticate(QStringLiteral("lightdm-deepin-greeter"), QStringLiteral("Set num lock state")); + m_fakeInput->requestKeyboardKeyPress(KEY_NUMLOCK); + m_fakeInput->requestKeyboardKeyRelease(KEY_NUMLOCK); + m_repeatTimer->start(); + m_numLockOn = !m_numLockOn; + return true; + } + qDebug() << "Fake input is not ready"; return false; } -void KeyboardPlantformWayland::run() +void KeyboardPlatformWayland::run() { + connect(m_connectionThreadObject, &ConnectionThread::connected, this, [this] { + m_eventQueue = new EventQueue(this); + m_eventQueue->setup(m_connectionThreadObject); + Registry *registry = new Registry(this); + setupRegistry(registry); + }, Qt::QueuedConnection + ); + m_connectionThreadObject->moveToThread(m_connectionThread); + m_connectionThread->start(); + m_connectionThreadObject->initConnection(); } + +void KeyboardPlatformWayland::setupRegistry(Registry *registry) +{ + qCInfo(DDE_SHELL) << "Set up registry: " << registry; + connect(registry, &Registry::ddeSeatAnnounced, this, [this, registry](quint32 name, quint32 version) { + m_ddeSeat = registry->createDDESeat(name, version, this); + if (m_ddeSeat) { + // 先断开连接在重新连接,防止多次创建之后,导致重复连接 + disconnect(m_ddeKeyboard, &DDEKeyboard::keyChanged, this, nullptr); + m_ddeKeyboard = m_ddeSeat->createDDEKeyboard(this); + connect(m_ddeKeyboard, &DDEKeyboard::keyChanged, this, [this](quint32 key, KWayland::Client::DDEKeyboard::KeyState state, quint32 time) { + if (state == KWayland::Client::DDEKeyboard::KeyState::Pressed) { + if (key == KEY_CAPSLOCK) { + m_capsLock = !m_capsLock; + qDebug() << "CapsLock state: " << m_capsLock; + Q_EMIT capsLockStatusChanged(m_capsLock); + } else if (key == KEY_NUMLOCK) { + if (m_repeatTimer->isActive()) + return; + + m_numLockOn = !m_numLockOn; + qDebug() << "NumLock state: " << m_numLockOn; + Q_EMIT numLockStatusChanged(m_numLockOn); + } + } + }); + } + }); + + connect(registry, &Registry::fakeInputAnnounced, this, [ this, registry ](quint32 name, quint32 version) { + qDebug() << "Create fakeinput."; + m_fakeInput = registry->createFakeInput(name, version, this); + if (!m_fakeInput->isValid()) { + qCWarning(DDE_SHELL) << "Create fakeinput failed."; + return; + } + + Q_EMIT initialized(); + }); + + registry->setEventQueue(m_eventQueue); + registry->create(m_connectionThreadObject); + registry->setup(); +} + +// 对于dde-lock需要初始化大小写状态 +void KeyboardPlatformWayland::initStatus() +{ + QDBusMessage message = QDBusMessage::createMethodCall("org.kde.KWin", "/Xkb", "org.kde.kwin.Xkb", "getLeds"); + QDBusPendingCall async = QDBusConnection::sessionBus().asyncCall(message); + auto *watcher = new QDBusPendingCallWatcher(async); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher](QDBusPendingCallWatcher *callWatcher) { + QDBusPendingReply reply = *callWatcher; + if (!reply.isError()) { + int locked = reply.argumentAt(0).toInt(); + m_capsLock = (locked & 0x02) != 0; + // 异步结果通过信号发布 + Q_EMIT capsLockStatusChanged(m_capsLock); + qCDebug(DDE_SHELL) << "capslock status init : " << m_capsLock; + + // greeter中numlock状态来自配置 + if (qApp && qApp->applicationName().contains("lock")) { + m_numLockOn = (locked & 0x10) != 0; + Q_EMIT numLockStatusChanged(m_numLockOn); + qCDebug(DDE_SHELL) << "numlock status init : " << m_numLockOn; + } + } else { + qCWarning(DDE_SHELL) << "failed to init caps/num lock status :" << reply.error().message(); + } + + callWatcher->deleteLater(); + watcher->deleteLater(); + }); +} + +void KeyboardPlatformWayland::ungrabKeyboard() +{ + QProcess::execute("bash -c \"originmap=$(setxkbmap -query | grep option | awk -F ' ' '{print $2}');/usr/bin/setxkbmap -option grab:break_actions&&/usr/bin/xdotool key XF86Ungrab&&setxkbmap -option $originmap\""); +} + +#endif diff --git a/src/global_util/keyboardmonitor/keyboardplantform_wayland.h b/src/global_util/keyboardmonitor/keyboardplantform_wayland.h index 90925408..ba7e553b 100644 --- a/src/global_util/keyboardmonitor/keyboardplantform_wayland.h +++ b/src/global_util/keyboardmonitor/keyboardplantform_wayland.h @@ -1,46 +1,63 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef KEYBOARDPLANTFORM_WAYLAND_H #define KEYBOARDPLANTFORM_WAYLAND_H +#ifdef USE_DEEPIN_WAYLAND + #include "keyboardplatform.h" -class KeyboardPlantformWayland : public KeyBoardPlatform +#include + +class QThread; + +namespace KWayland +{ +namespace Client +{ + class Registry; + class ConnectionThread; + class DDEKeyboard; + class DDESeat; + class EventQueue; + class FakeInput; +} +} +using namespace KWayland::Client; +class KeyboardPlatformWayland : public KeyBoardPlatform { Q_OBJECT public: - KeyboardPlantformWayland(QObject *parent = nullptr); - - bool isCapslockOn() override; - bool isNumlockOn() override; - bool setNumlockStatus(const bool &on) override; + KeyboardPlatformWayland(QObject *parent = nullptr); + virtual ~KeyboardPlatformWayland(); -signals: - void capslockStatusChanged(bool on); - void numlockStatusChanged(bool on); + bool isCapsLockOn() override; + bool isNumLockOn() override; + bool setNumLockStatus(const bool &on) override; + void ungrabKeyboard() override; protected: void run() Q_DECL_OVERRIDE; + +private: + void setupRegistry(Registry *registry); + void initStatus(); + +private: + QThread *m_connectionThread; + ConnectionThread *m_connectionThreadObject; + DDEKeyboard *m_ddeKeyboard; + FakeInput *m_fakeInput; + DDESeat *m_ddeSeat; + EventQueue *m_eventQueue; + bool m_capsLock; + bool m_numLockOn; + QTimer *m_repeatTimer; }; +#endif + #endif // KEYBOARDPLANTFORM_WAYLAND_H diff --git a/src/global_util/keyboardmonitor/keyboardplantform_x11.cpp b/src/global_util/keyboardmonitor/keyboardplantform_x11.cpp index 999423a8..2dd44267 100644 --- a/src/global_util/keyboardmonitor/keyboardplantform_x11.cpp +++ b/src/global_util/keyboardmonitor/keyboardplantform_x11.cpp @@ -1,37 +1,18 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * zorowk - * - * Maintainer: sbw - * kirigaya - * Hualet - * zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "keyboardplantform_x11.h" +#include "constants.h" +#ifdef ENABLE_DSS_SNIPE +#include +#else #include +#endif #include #include -#include #include #include #include @@ -40,11 +21,10 @@ #include #include -#include static int xi2_opcode; -int KeyboardPlantformX11::xinput_version(Display *display) +int KeyboardPlatformX11::xinput_version(Display *display) { XExtensionVersion *version; static int vers = -1; @@ -81,7 +61,7 @@ int KeyboardPlantformX11::xinput_version(Display *display) return vers; } -void KeyboardPlantformX11::select_events(Display* display) +void KeyboardPlatformX11::select_events(Display* display) { XIEventMask m; m.deviceid = XIAllMasterDevices; @@ -103,7 +83,7 @@ void KeyboardPlantformX11::select_events(Display* display) XSync(display, False); } -int KeyboardPlantformX11::listen(Display *display) +int KeyboardPlatformX11::listen(Display *display) { Window root = DefaultRootWindow(display); int root_x, root_y, nouse; @@ -134,9 +114,9 @@ int KeyboardPlantformX11::listen(Display *display) break; case XI_RawKeyRelease: if (event->detail == 66) { // check if the key pressed is capslock first. - emit capslockStatusChanged(isCapslockOn()); + emit capsLockStatusChanged(isCapsLockOn()); } else if (event->detail == 77) { - emit numlockStatusChanged(isNumlockOn()); + emit numLockStatusChanged(isNumLockOn()); } /*printf("Key release: Detail(%d), X(%d), Y(%d), Mask(%u)\n", event->detail, root_x, root_y, mask);*/ break; @@ -157,13 +137,14 @@ int KeyboardPlantformX11::listen(Display *display) return EXIT_SUCCESS; } -KeyboardPlantformX11::KeyboardPlantformX11(QObject *parent) +#ifndef ENABLE_DSS_SNIPE +KeyboardPlatformX11::KeyboardPlatformX11(QObject *parent) : KeyBoardPlatform(parent) { } -bool KeyboardPlantformX11::isCapslockOn() +bool KeyboardPlatformX11::isCapsLockOn() { bool result = false; unsigned int n = 0; @@ -175,7 +156,7 @@ bool KeyboardPlantformX11::isCapslockOn() return result; } -bool KeyboardPlantformX11::isNumlockOn() +bool KeyboardPlatformX11::isNumLockOn() { bool result; unsigned int n = 0; @@ -189,7 +170,7 @@ bool KeyboardPlantformX11::isNumlockOn() return result; } -bool KeyboardPlantformX11::setNumlockStatus(const bool &on) +bool KeyboardPlatformX11::setNumLockStatus(const bool &on) { Display* d = QX11Info::display(); if (!d) @@ -217,7 +198,7 @@ bool KeyboardPlantformX11::setNumlockStatus(const bool &on) return pressExit == 0 && releseExit == 0; } -void KeyboardPlantformX11::run() +void KeyboardPlatformX11::run() { Display* display = XOpenDisplay(nullptr); int event, error; @@ -235,3 +216,103 @@ void KeyboardPlantformX11::run() select_events(display); listen(display); } + +void KeyboardPlatformX11::ungrabKeyboard() +{ + static Display *d = QX11Info::display(); + if (d == NULL) { + fprintf(stderr, "display pointer is NULL when try ungrab keyboard.\n"); + return; + } + + XUngrabKeyboard(d, CurrentTime); +} +#else +KeyboardPlatformX11::KeyboardPlatformX11(QObject *parent) + : KeyBoardPlatform(parent) +{ + if (auto x11Application = qGuiApp->nativeInterface()) + m_display = x11Application->display(); +} + +bool KeyboardPlatformX11::isCapsLockOn() +{ + bool result = false; + unsigned int n = 0; + if (m_display) { + XkbGetIndicatorState(m_display, XkbUseCoreKbd, &n); + result = (n & 0x01) != 0; + } + + return result; +} + +bool KeyboardPlatformX11::isNumLockOn() +{ + bool result = false; + unsigned int n = 0; + if (!m_display) + return false; + + XkbGetIndicatorState(m_display, XkbUseCoreKbd, &n); + result = (n & 0x02) != 0; + + return result; +} + +bool KeyboardPlatformX11::setNumLockStatus(const bool &on) +{ + if (!m_display) + return false; + + XKeyboardState x; + XGetKeyboardControl(m_display, &x); + const bool numLockEnabled = x.led_mask & 2; + + if (numLockEnabled == on) { + return true; + } + + // Get the keycode for XK_Caps_Lock keysymbol + unsigned int keycode = XKeysymToKeycode(m_display, XK_Num_Lock); + + // Simulate Press + int pressExit = XTestFakeKeyEvent(m_display, keycode, True, CurrentTime); + XFlush(m_display); + + // Simulate Release + int releseExit = XTestFakeKeyEvent(m_display, keycode, False, CurrentTime); + XFlush(m_display); + + return pressExit == 0 && releseExit == 0; +} + +void KeyboardPlatformX11::run() +{ + Display* display = XOpenDisplay(nullptr); + int event, error; + + if (!XQueryExtension(display, "XInputExtension", &xi2_opcode, &event, &error)) { + fprintf(stderr, "XInput2 not available.\n"); + return; + } + + if (!xinput_version(display)) { + fprintf(stderr, "XInput2 extension not available\n"); + return; + } + + select_events(display); + listen(display); +} + +void KeyboardPlatformX11::ungrabKeyboard() +{ + if (!m_display) { + fprintf(stderr, "display pointer is NULL when try ungrab keyboard.\n"); + return; + } + + XUngrabKeyboard(m_display, CurrentTime); +} +#endif \ No newline at end of file diff --git a/src/global_util/keyboardmonitor/keyboardplantform_x11.h b/src/global_util/keyboardmonitor/keyboardplantform_x11.h index ad20af26..c4800495 100644 --- a/src/global_util/keyboardmonitor/keyboardplantform_x11.h +++ b/src/global_util/keyboardmonitor/keyboardplantform_x11.h @@ -1,29 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * zorowk - * - * Maintainer: sbw - * kirigaya - * Hualet - * zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef KEYBOARDPLANTFORM_X11_H #define KEYBOARDPLANTFORM_X11_H @@ -32,21 +9,27 @@ typedef struct _XDisplay Display; -class KeyboardPlantformX11 : public KeyBoardPlatform +class KeyboardPlatformX11 : public KeyBoardPlatform { Q_OBJECT public: - KeyboardPlantformX11(QObject *parent = nullptr); + KeyboardPlatformX11(QObject *parent = nullptr); - bool isCapslockOn() override; - bool isNumlockOn() override; - bool setNumlockStatus(const bool &on) override; + bool isCapsLockOn() override; + bool isNumLockOn() override; + bool setNumLockStatus(const bool &on) override; void run() override; + void ungrabKeyboard() override; private: int listen(Display *display); static int xinput_version(Display *display); static void select_events(Display* display); + +#ifdef ENABLE_DSS_SNIPE +private: + Display *m_display = nullptr; +#endif }; #endif // KEYBOARDPLANTFORM_X11_H diff --git a/src/global_util/keyboardmonitor/keyboardplatform.cpp b/src/global_util/keyboardmonitor/keyboardplatform.cpp index 5813354d..0d36edd1 100644 --- a/src/global_util/keyboardmonitor/keyboardplatform.cpp +++ b/src/global_util/keyboardmonitor/keyboardplatform.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "keyboardplatform.h" diff --git a/src/global_util/keyboardmonitor/keyboardplatform.h b/src/global_util/keyboardmonitor/keyboardplatform.h index 54c10404..a2f376f4 100644 --- a/src/global_util/keyboardmonitor/keyboardplatform.h +++ b/src/global_util/keyboardmonitor/keyboardplatform.h @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef KEYBOARDPLATFORM_H #define KEYBOARDPLATFORM_H @@ -31,14 +14,16 @@ class KeyBoardPlatform : public QObject KeyBoardPlatform(QObject *parent = nullptr); virtual ~KeyBoardPlatform(); - virtual bool isCapslockOn() = 0; - virtual bool isNumlockOn() = 0; - virtual bool setNumlockStatus(const bool &on) = 0; + virtual bool isCapsLockOn() = 0; + virtual bool isNumLockOn() = 0; + virtual bool setNumLockStatus(const bool &on) = 0; virtual void run() = 0; + virtual void ungrabKeyboard() = 0; signals: - void capslockStatusChanged(bool on); - void numlockStatusChanged(bool on); + void capsLockStatusChanged(bool on); + void numLockStatusChanged(bool on); + void initialized(); }; #endif // KEYBOARDPLATFORM_H diff --git a/src/global_util/modules_loader.cpp b/src/global_util/modules_loader.cpp deleted file mode 100644 index 695acf0e..00000000 --- a/src/global_util/modules_loader.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "modules_loader.h" - -#include "base_module_interface.h" - -#include -#include -#include -#include - -namespace dss { -namespace module { - -const QString ModulesDir = "/usr/lib/dde-session-shell/modules"; - -ModulesLoader::ModulesLoader(QObject *parent) - : QThread(parent) -{ -} - -ModulesLoader::~ModulesLoader() -{ -} - -ModulesLoader &ModulesLoader::instance() -{ - static ModulesLoader modulesLoader; - return modulesLoader; -} - -BaseModuleInterface *ModulesLoader::findModuleByName(const QString &name) const -{ - return m_modules.value(name, nullptr); -} - -QHash ModulesLoader::findModulesByType(const int type) const -{ - QHash modules; - for (BaseModuleInterface *module : m_modules.values()) { - if (module->type() == type) { - modules.insert(module->key(), module); - } - } - return modules; -} - -void ModulesLoader::run() -{ - findModule(ModulesDir); -} - -bool ModulesLoader::checkVersion(const QString &target, const QString &base) -{ - if (target == base) { - return true; - } - const QStringList baseVersion = base.split("."); - const QStringList targetVersion = target.split("."); - - const int baseVersionSize = baseVersion.size(); - const int targetVersionSize = targetVersion.size(); - const int size = baseVersionSize < targetVersionSize ? baseVersionSize : targetVersionSize; - - for (int i = 0; i < size; i++) { - if (targetVersion[i] == baseVersion[i]) continue; - return targetVersion[i].toInt() > baseVersion[i].toInt() ? true : false; - } - return true; -} - -void ModulesLoader::findModule(const QString &path) -{ - QDir dir(path); - if (!dir.exists()) { - qDebug() << path << "is not exists."; - return; - } - const QFileInfoList modules = dir.entryInfoList(); - for (QFileInfo module : modules) { - const QString path = module.absoluteFilePath(); - if (!QLibrary::isLibrary(path)) { - continue; - } - qInfo() << module << "is found"; - QPluginLoader loader(path); - const QJsonObject &meta = loader.metaData().value("MetaData").toObject(); - if (!checkVersion(meta.value("api").toString(), "1.0.0")) { - qWarning() << "The module version is too low."; - continue; - } - BaseModuleInterface *moduleInstance = dynamic_cast(loader.instance()); - if (!moduleInstance) { - qWarning() << loader.errorString(); - continue; - } - if (m_modules.contains(moduleInstance->key())) { - continue; - } - m_modules.insert(moduleInstance->key(), moduleInstance); - emit moduleFound(moduleInstance); - } -} - -} // namespace module -} // namespace dss diff --git a/src/global_util/modules_loader.h b/src/global_util/modules_loader.h deleted file mode 100644 index 9586b1ba..00000000 --- a/src/global_util/modules_loader.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#ifndef MODULES_LOADER_H -#define MODULES_LOADER_H - -#include -#include - -namespace dss { -namespace module { - -class BaseModuleInterface; -class ModulesLoader : public QThread -{ - Q_OBJECT -public: - static ModulesLoader &instance(); - - inline QHash moduleList() { return m_modules; } - BaseModuleInterface *findModuleByName(const QString &name) const; - QHash findModulesByType(const int type) const; - -signals: - void moduleFound(BaseModuleInterface *); - -protected: - void run() override; - -private: - explicit ModulesLoader(QObject *parent = nullptr); - ~ModulesLoader() override; - ModulesLoader(const ModulesLoader &) = delete; - ModulesLoader &operator=(const ModulesLoader &) = delete; - - bool checkVersion(const QString &target, const QString &base); - void findModule(const QString &path); - -private: - QHash m_modules; -}; - -} // namespace module -} // namespace dss -#endif // MODULES_LOADER_H diff --git a/src/global_util/multiscreenmanager.cpp b/src/global_util/multiscreenmanager.cpp index d20e8847..418bf73e 100644 --- a/src/global_util/multiscreenmanager.cpp +++ b/src/global_util/multiscreenmanager.cpp @@ -1,18 +1,30 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "multiscreenmanager.h" #include "fullscreenbackground.h" +#include "constants.h" #include -#include #include -#include #include #include +#ifndef ENABLE_DSS_SNIPE +#include +#else +#include +#endif +#include + +#include "dbusconstant.h" + MultiScreenManager::MultiScreenManager(QObject *parent) : QObject(parent) , m_registerFunction(nullptr) , m_raiseContentFrameTimer(new QTimer(this)) - , m_systemDisplay(new SystemDisplayInter("com.deepin.system.Display", "/com/deepin/system/Display", QDBusConnection::systemBus(), this)) + , m_systemDisplay(new SystemDisplayInter(DSS_DBUS::systemDisplayService, DSS_DBUS::systemDisplayPath, QDBusConnection::systemBus(), this)) , m_isCopyMode(false) { connect(qApp, &QGuiApplication::screenAdded, this, &MultiScreenManager::onScreenAdded, Qt::DirectConnection); @@ -29,33 +41,91 @@ MultiScreenManager::MultiScreenManager(QObject *parent) } } -void MultiScreenManager::register_for_mutil_screen(std::function function) +void MultiScreenManager::register_for_multi_screen(std::function function) { m_registerFunction = function; - qInfo() << Q_FUNC_INFO << ", is copy mode: " << m_isCopyMode; + qCInfo(DDE_SHELL) << "Copy mode:" << m_isCopyMode; + + int maxAttempts = 0; + while (true) { + if (qApp->screens().count() < 1) { + // 没有屏幕数据延时2s再取一次 + QThread::sleep(2); + qWarning(" #### qApp->screens : %d, repeat times : %d .", qApp->screens().count(), maxAttempts++); + if (maxAttempts == 50) { + break; + } + } else { + break; + } + } + // update all screen if (m_isCopyMode) { - if (!qApp->screens().isEmpty()) - onScreenAdded(qApp->screens().first()); + if (!qApp->screens().isEmpty()) { + QScreen *validScreen = nullptr; + for (QScreen *screen : qApp->screens()) { + // 留下一个可用的屏幕 + if (!screen->name().isEmpty()) { + validScreen = screen; + break; + } + } + if (!validScreen) + return; + onScreenAdded(validScreen); + } } else { for (QScreen *screen : qApp->screens()) { + // 当greeter刚起来处理第一个屏幕时,第二个屏幕被拔掉,这时第二个屏幕指针被释放,不应该在继续处理,否则会导致崩溃 + if (!qApp->screens().contains(screen)) { + qCWarning(DDE_SHELL) << "Screen pointer has been released"; + continue; + } onScreenAdded(screen); } } } -void MultiScreenManager::startRaiseContentFrame() +void MultiScreenManager::startRaiseContentFrame(const bool visible) { - m_raiseContentFrameTimer->start(); + if (visible) { + m_raiseContentFrameTimer->start(); + } +} + +bool MultiScreenManager::eventFilter(QObject *watched, QEvent *event) +{ + // 捕获lockframe窗口显示事件 + if (event->type() == QEvent::Show) { + QWidget *widget = qobject_cast(watched); + if (widget && m_frames.values().contains(widget)) { + // 显示的时候获取窗口位置信息(调试) + QTimer::singleShot(0, this, &MultiScreenManager::checkLockFrameLocation); + } + } + + return QObject::eventFilter(watched, event); } void MultiScreenManager::onScreenAdded(QPointer screen) { - qInfo() << Q_FUNC_INFO << ", is copy mode: " << m_isCopyMode << ", screen: " << screen; + qCInfo(DDE_SHELL) << "Is copy mode:" << m_isCopyMode << ", screen: " << screen; + + // 虚拟屏幕不处理 + if (screen.isNull() || (screen->name().isEmpty() && (screen->geometry().width() == 0 || screen->geometry().height() == 0))) { + return; + } + if (!m_registerFunction) { return; } + qCInfo(DDE_SHELL) << "onScreenAdded processing, screen:" << screen + << ", name:" << screen->name() + << ", geometry:" << screen->geometry() + << ", existing frames count:" << m_frames.size(); + QWidget* w = nullptr; if (m_isCopyMode) { // 如果m_frames不为空则直接退出 @@ -70,6 +140,10 @@ void MultiScreenManager::onScreenAdded(QPointer screen) // 如果指针为空,则不加入Map中,并析构创建的全屏窗口。 if (w && !screen.isNull()) { m_frames[screen] = w; + // wayland下没有屏幕时,容易导致qt崩溃 + if (!QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) { + w->installEventFilter(this); + } } else if (w) { w->deleteLater(); } @@ -79,7 +153,13 @@ void MultiScreenManager::onScreenAdded(QPointer screen) void MultiScreenManager::onScreenRemoved(QPointer screen) { - qDebug() << Q_FUNC_INFO << " is copy mode: " << m_isCopyMode << ", screen: " << screen; + qDebug() << "Is copy mode: " << m_isCopyMode << ", screen: " << screen; + // 虚拟屏幕不处理 + if (screen.isNull() || (screen->name().isEmpty() && (screen->geometry().width() == 0 || screen->geometry().height() == 0))) { + qCWarning(DDE_SHELL) << "Remove skipped, screen error"; + return; + } + if (!m_registerFunction) { return; } @@ -89,13 +169,24 @@ void MultiScreenManager::onScreenRemoved(QPointer screen) QWidget *frame = m_frames[screen]; m_frames.remove(screen); // 如果此时m_frames为空则其它的屏幕继续使用此frame,不重新创建 + QScreen *validScreen = nullptr; if (!qApp->screens().isEmpty() && m_frames.isEmpty()) { - QScreen *screen = qApp->screens().first(); + for (QScreen *screen : qApp->screens()) { + // 留下一个可用的屏幕 + if (!screen->name().isEmpty()) { + validScreen = screen; + break; + } + } + if (!validScreen) { + frame->deleteLater(); + return; + } // 更新frame绑定的屏幕 - m_frames[screen] = frame; - FullscreenBackground *fullScreenFrame = qobject_cast(frame); - if (fullScreenFrame) { - fullScreenFrame->setScreen(screen, true); + m_frames[validScreen] = frame; + AbstractFullBackgroundInterface *fullScreenFrameInterface = dynamic_cast(frame); + if (fullScreenFrameInterface) { + fullScreenFrameInterface->setScreen(validScreen, true); } } else { frame->deleteLater(); @@ -104,16 +195,36 @@ void MultiScreenManager::onScreenRemoved(QPointer screen) m_frames[screen]->deleteLater(); m_frames.remove(screen); } + updateFrame(); } startRaiseContentFrame(); } +void MultiScreenManager::updateFrame() +{ + for (const auto screen : m_frames.keys()) { + FullScreenBackground *fullScreenFrame = qobject_cast(m_frames[screen]); + if (fullScreenFrame) { + fullScreenFrame->setScreen(screen, true); + } + } +} + void MultiScreenManager::raiseContentFrame() { for (auto it = m_frames.constBegin(); it != m_frames.constEnd(); ++it) { - if (it.value()->property("contentVisible").toBool()) { + if (it.value() && it.value()->property("contentVisible").toBool()) { it.value()->raise(); + if (QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) { + it.value()->activateWindow(); + it.value()->setFocus(); + } + + // bug189309, 重启或注锁后,后端屏幕变化通知太晚 + // 触发move事件处理content是否显示 + it.value()->updateGeometry(); + return; } } @@ -123,21 +234,79 @@ void MultiScreenManager::onDisplayModeChanged(const QString &) { m_isCopyMode = (COPY_MODE == getDisplayModeByConfig(m_systemDisplay->GetConfig())); - qInfo() << Q_FUNC_INFO << ", copy mode: " << m_isCopyMode << ", screen size: " << qApp->screens().size(); + qCInfo(DDE_SHELL) << "Display mode changed, copy mode: " << m_isCopyMode << ", screen size: " << qApp->screens().size(); if (m_isCopyMode) { + QScreen *validScreen = nullptr; for (QScreen *screen : qApp->screens()) { - // 留下一个屏即可 - if (screen != qApp->screens().first()) + if (screen->name().isEmpty()) + continue; + if (!validScreen) + validScreen = screen; + // 留下一个可用的屏 + if (screen != validScreen) onScreenRemoved(screen); } } else { for (QScreen *screen : qApp->screens()) { - if (!m_frames[screen]) + if (!m_frames.contains(screen)) onScreenAdded(screen); } } } +void MultiScreenManager::checkLockFrameLocation() +{ + xcb_connection_t *connection = nullptr; + if (!QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) { +#ifndef ENABLE_DSS_SNIPE + connection = QX11Info::connection(); +#else + auto *x11App = qGuiApp->nativeInterface(); + if (x11App) + connection = x11App->connection(); +#endif + } + + for (QScreen *screen : m_frames.keys()) { + if (screen) { + QWidget *frame = m_frames.value(screen); + qCInfo(DDE_SHELL) << "Check lock frame location, screen:" << screen + << ", screen name:" << screen->name() + << ", screen geometry:" << screen->geometry() + << ", lockframe:" << frame + << ", Qt frame geometry:" << frame->geometry(); + + // 通过 XCB 检查窗口在 X Server 中的实际位置 + // 注意:X11 下窗口位置不乘 DPR(与 RandR 物理坐标一致),窗口大小乘 DPR + if (connection && frame) { + auto cookie = xcb_get_geometry(connection, static_cast(frame->winId())); + auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr); + if (reply) { + QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height); + const qreal dpr = frame->devicePixelRatioF(); + QRect expectedPhysical(screen->geometry().x(), screen->geometry().y(), + qRound(screen->geometry().width() * dpr), + qRound(screen->geometry().height() * dpr)); + bool positionMatch = (xcbGeometry == expectedPhysical); + qCInfo(DDE_SHELL) << " XCB actual geometry(physical):" << xcbGeometry + << ", expected(physical):" << expectedPhysical + << ", dpr:" << dpr + << ", match:" << positionMatch; + if (!positionMatch) { + qCWarning(DDE_SHELL) << " *** POSITION MISMATCH DETECTED! ***" + << "XCB geometry:" << xcbGeometry + << "expected:" << expectedPhysical + << "for screen" << screen->name(); + } + free(reply); + } else { + qCWarning(DDE_SHELL) << " Failed to get XCB geometry for frame:" << frame; + } + } + } + } +} + int MultiScreenManager::getDisplayModeByConfig(const QString &config) const { if (config.isEmpty()) @@ -152,4 +321,4 @@ int MultiScreenManager::getDisplayModeByConfig(const QString &config) const } return EXTENDED_MODE; -} \ No newline at end of file +} diff --git a/src/global_util/multiscreenmanager.h b/src/global_util/multiscreenmanager.h index fc467406..c08e8618 100644 --- a/src/global_util/multiscreenmanager.h +++ b/src/global_util/multiscreenmanager.h @@ -1,15 +1,25 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef MULTISCREENMANAGER_H #define MULTISCREENMANAGER_H -#include #include #include #include #include -#include + +#ifdef ENABLE_DSS_SNIPE +#include "systemdisplay1interface.h" + +using SystemDisplayInter = org::deepin::dde::Display1; +#else #include using SystemDisplayInter = com::deepin::system::Display; +#endif + const static int COPY_MODE = 1; const static int EXTENDED_MODE = 2; @@ -20,17 +30,22 @@ class MultiScreenManager : public QObject public: explicit MultiScreenManager(QObject *parent = nullptr); - void register_for_mutil_screen(std::function function); - void startRaiseContentFrame(); + void register_for_multi_screen(std::function function); + void startRaiseContentFrame(const bool visible = true); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; private: void onScreenAdded(QPointer screen); void onScreenRemoved(QPointer screen); void raiseContentFrame(); int getDisplayModeByConfig(const QString &config) const; + void updateFrame(); private slots: void onDisplayModeChanged(const QString &); + void checkLockFrameLocation(); private: std::function , int)> m_registerFunction; diff --git a/src/global_util/plugin_manager/login_plugin.cpp b/src/global_util/plugin_manager/login_plugin.cpp new file mode 100644 index 00000000..8c504d2e --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin.cpp @@ -0,0 +1,215 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login_plugin.h" +#include "public_func.h" + +LoginPlugin::LoginPlugin(dss::module::BaseModuleInterface *module, QObject *parent) + : PluginBase(module, parent) + , m_authType(AuthType::AT_Password) +{ + +} + +bool LoginPlugin::isPluginEnabled() +{ + QJsonObject message; + message["CmdType"] = "IsPluginEnabled"; + + const QString &result = this->message(toJson(message)); + qCDebug(DDE_SHELL) << key() << " get enabled state result: " << result; + const QJsonObject &dataObj = getDataObj(result); + if (dataObj.isEmpty() || !dataObj.contains("IsPluginEnabled")) + return true; + + return dataObj["IsPluginEnabled"].toBool(true); +} + +int LoginPlugin::level() +{ + QJsonObject message { + {"CmdType", "GetLevel"} + }; + + const QString &result = this->message(toJson(message)); + const QJsonObject &dataObj = getDataObj(result); + if (!dataObj.contains("Level")) { + return 1; + } + + return dataObj["Level"].toInt(1); +} + +int LoginPlugin::loginType() +{ + QJsonObject message { + {"CmdType", "GetLoginType"} + }; + + const QString &result = this->message(toJson(message)); + qCDebug(DDE_SHELL) << "Login type, result: " << result; + const QJsonObject &dataObj = getDataObj(result); + if (!dataObj.contains("LoginType")) { + return CustomLoginType::CLT_Default; + } + + return dataObj["LoginType"].toInt(CustomLoginType::CLT_Default); +} + +bool LoginPlugin::hasSecondLevel(const QString &user) +{ + QJsonObject message { + {"CmdType", "HasSecondLevel"}, + {"Data", user} + }; + + const QString &result = this->message(toJson(message)); + const QJsonObject &dataObj = getDataObj(result); + if (!dataObj.contains("HasSecondLevel")) { + return false; + } + + return dataObj["HasSecondLevel"].toBool(false); +} + +int LoginPlugin::updateLoginType() +{ + QJsonObject message { + {"CmdType", "UpdateLoginType"} + }; + + const QString &result = this->message(toJson(message)); + qCDebug(DDE_SHELL) << "Update login type, result: " << result; + const QJsonObject &dataObj = getDataObj(result); + if (!dataObj.contains("LoginType")) { + return CustomLoginType::CLT_Default; + } + + return dataObj["LoginType"].toInt(CustomLoginType::CLT_Default); +} + +int LoginPlugin::sessionTimeout() +{ + QJsonObject message { + {"CmdType", "GetSessionTimeout"} + }; + + const QString &result = this->message(toJson(message)); + qCDebug(DDE_SHELL) << "Get session timeout, result: " << result; + const QJsonObject &dataObj = getDataObj(result); + if (!dataObj.contains("SessionTimeout")) { + return DEFAULT_SESSION_TIMEOUT; + } + + return dataObj["SessionTimeout"].toInt(DEFAULT_SESSION_TIMEOUT); +} + +bool LoginPlugin::supportDefaultUser() +{ + QJsonObject message; + message["CmdType"] = "GetConfigs"; + const QString &result = this->message(toJson(message)); + const QJsonObject &dataObj = getDataObj(result); + if (dataObj.isEmpty()) + return true; + + return dataObj["SupportDefaultUser"].toBool(true); +} + +void LoginPlugin::notifyCurrentUserChanged(const QString &userName, uid_t uid) +{ + QJsonObject message; + message["CmdType"] = "CurrentUserChanged"; + QJsonObject user; + user["Name"] = userName; + user["Uid"] = static_cast(uid); + message["Data"] = user; + + this->message(toJson(message)); +} + + +void LoginPlugin::authStateChanged(AuthCommon::AuthType type, AuthCommon::AuthState state, const QString &prompt) +{ + QJsonObject message; + message["CmdType"] = "AuthState"; + QJsonObject retDataObj; + retDataObj["AuthType"] = static_cast(type); + retDataObj["AuthState"] = state; + retDataObj["AuthPrompt"] = prompt; + message["Data"] = retDataObj; + + this->message(toJson(message)); +} + +void LoginPlugin::updateConfig() +{ + QJsonObject message; + message["CmdType"] = "GetConfigs"; + QString result = this->message(toJson(message)); + qCInfo(DDE_SHELL) << "Get configs result: " << result; + + QJsonParseError jsonParseError; + const QJsonDocument resultDoc = QJsonDocument::fromJson(result.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || resultDoc.isEmpty()) { + qCWarning(DDE_SHELL) << "Result json parse error, error: " << jsonParseError.error; + return; + } + + QJsonObject resultObj = resultDoc.object(); + if (!resultObj.contains("Data")) { + qCWarning(DDE_SHELL) << "Result doesn't contains the 'data' field"; + return; + } + + QJsonObject dataObj = resultObj["Data"].toObject(); + m_pluginConfig.showAvatar = dataObj["ShowAvatar"].toBool(m_pluginConfig.showAvatar); + m_pluginConfig.showUserName = dataObj["ShowUserName"].toBool(m_pluginConfig.showUserName); + m_pluginConfig.showSwitchButton = dataObj["ShowSwitchButton"].toBool(m_pluginConfig.showSwitchButton); + m_pluginConfig.showLockButton = dataObj["ShowLockButton"].toBool(m_pluginConfig.showLockButton); + m_pluginConfig.defaultAuthLevel = (DefaultAuthLevel)dataObj["DefaultAuthLevel"].toInt(); + m_pluginConfig.showBackGroundColor = dataObj["ShowBackGroundColor"].toBool(m_pluginConfig.showBackGroundColor); + m_pluginConfig.switchUserWhenCheckAccount = dataObj["SwitchUserWhenCheckAccount"].toBool(m_pluginConfig.switchUserWhenCheckAccount); + m_pluginConfig.notUsedByLoginedUserInGreeter = dataObj["NotUsedByLoginedUserInGreeter"].toBool(m_pluginConfig.notUsedByLoginedUserInGreeter); + m_pluginConfig.saveLastAuthType = dataObj["SaveLastAuthType"].toBool(m_pluginConfig.saveLastAuthType); + if (dataObj.contains("AssignAuthType")) + m_pluginConfig.assignAuthType = static_cast(dataObj["AssignAuthType"].toInt()); + m_authType = (AuthType)dataObj["AuthType"].toInt(); +} + +void LoginPlugin::accountError() +{ + QJsonObject jsonObject; + jsonObject["CmdType"] = "AccountError"; + this->message(toJson(jsonObject)); +} + +void LoginPlugin::notifyAuthFactorsChanged(int authFactors) +{ + QJsonObject message; + message["CmdType"] = "AuthFactorsChanged"; + QJsonObject data; + data["AuthFactors"] = authFactors; + message["Data"] = data; + + this->message(toJson(message)); +} + +/** + * @brief + * + * @return true 插件已经准备好做认证了(一般是用户已经输入了内容,比如验证码) + * @return false + */ +bool LoginPlugin::readyToAuth() +{ + QJsonObject message; + message["CmdType"] = "ReadyToAuth"; + const QString &result = this->message(toJson(message)); + const QJsonObject &dataObj = getDataObj(result); + if (dataObj.isEmpty()) + return true; + + return dataObj["ReadyToAuth"].toBool(true); +} diff --git a/src/global_util/plugin_manager/login_plugin.h b/src/global_util/plugin_manager/login_plugin.h new file mode 100644 index 00000000..7a595ad9 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin.h @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGIN_PLUGIN_H +#define LOGIN_PLUGIN_H + +#include "plugin_base.h" +#include "login_module_interface_v2.h" +#include "authcommon.h" + +#include +#include + +#define DEFAULT_SESSION_TIMEOUT 15000 + +class LoginPlugin : public PluginBase +{ + Q_OBJECT +public: + using AuthCallbackData = dss::module_v2::AuthCallbackData; + using AuthCallbackFun = dss::module_v2::AuthCallbackFun; + using AuthResult = dss::module_v2::AuthResult; + using DefaultAuthLevel = dss::module::DefaultAuthLevel; + using AuthType = dss::module::AuthType; + using CustomLoginType = dss::module::CustomLoginType; + + // 认证插件配置 + struct PluginConfig + { + bool showAvatar = true; // 是否显示头像 + bool showUserName = true; // 是否显示用户名 + bool showSwitchButton = true; // 是否显示类型切换按钮 + bool showLockButton = true; // 是否显示解锁按钮 + bool showBackGroundColor = true; // 是否显示灰色背景 + bool switchUserWhenCheckAccount = true; // 检测用户已经登录后是否切换到这个已登录的用户 + bool notUsedByLoginedUserInGreeter = false; // 在登录界面且当前用户已登录时不使用插件 + bool saveLastAuthType = true; // 是否保存上一次认证类型 + // 默认使用此认证类型的强度 + DefaultAuthLevel defaultAuthLevel = DefaultAuthLevel::Default; + AuthCommon::AuthType assignAuthType = AuthCommon::AuthType::AT_Custom; + + bool operator==(const PluginConfig b) const + { + return this->showAvatar == b.showAvatar && + this->showLockButton == b.showAvatar && + this->showSwitchButton == b.showSwitchButton && + this->showUserName == b.showUserName && + this->defaultAuthLevel == b.defaultAuthLevel && + this->showBackGroundColor == b.showBackGroundColor && + this->switchUserWhenCheckAccount == b.switchUserWhenCheckAccount && + this->notUsedByLoginedUserInGreeter == b.notUsedByLoginedUserInGreeter && + this->saveLastAuthType == b.saveLastAuthType && + this->assignAuthType == b.assignAuthType; + } + + bool operator!=(const PluginConfig b) const + { + return this->showAvatar != b.showAvatar || + this->showLockButton != b.showAvatar || + this->showSwitchButton != b.showSwitchButton || + this->showUserName != b.showUserName || + this->defaultAuthLevel != b.defaultAuthLevel || + this->showBackGroundColor != b.showBackGroundColor || + this->switchUserWhenCheckAccount != b.switchUserWhenCheckAccount || + this->notUsedByLoginedUserInGreeter != b.notUsedByLoginedUserInGreeter || + this->saveLastAuthType != b.saveLastAuthType || + this->assignAuthType != b.assignAuthType; + } + }; + + explicit LoginPlugin(dss::module::BaseModuleInterface *module, QObject *parent = nullptr); + + virtual PluginBase::ModuleType type() const = 0; + + virtual void setAuthCallback(AuthCallbackFun) = 0; + + virtual void reset() = 0; + + bool isPluginEnabled(); + + int level(); // 插件所处层级 + + int loginType(); // 从插件获取登录类型: 默认、多因、第三方 + + bool hasSecondLevel(const QString &user); // 检查是否有第二层 + + int updateLoginType(); // 通知插件更新登录类型,登录类型信息依赖远程配置 + + int sessionTimeout(); // 插件自定义的会话超时时长,单位ms + + bool supportDefaultUser(); + + void notifyCurrentUserChanged(const QString &userName, uid_t uid); + + void notifyAuthFactorsChanged(int authFactors); + + void updateConfig(); + + void accountError(); + + inline AuthType defaultAuthType() const { return m_authType; } + + inline PluginConfig pluginConfig() const { return m_pluginConfig; } + + void authStateChanged(AuthCommon::AuthType type, AuthCommon::AuthState state, const QString &prompt); + + bool readyToAuth(); + +private: + PluginConfig m_pluginConfig; + AuthType m_authType; +}; + +#endif // LOGIN_PLUGIN_H diff --git a/src/global_util/plugin_manager/login_plugin_util.cpp b/src/global_util/plugin_manager/login_plugin_util.cpp new file mode 100644 index 00000000..e82872cd --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_util.cpp @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "login_plugin_util.h" + +#include "login_plugin.h" +#include "plugin_manager.h" + +int LPUtil::loginType() +{ + auto *plugin = getLevel2LoginPlugin(); + if (!plugin) { + return LoginPlugin::CustomLoginType::CLT_Default; + } + + return plugin->loginType(); +} + +int LPUtil::updateLoginType() +{ + auto plugin = getLevel2LoginPlugin(); + if (!plugin) { + return LoginPlugin::CustomLoginType::CLT_Default; + } + return plugin->updateLoginType(); +} + +int LPUtil::sessionTimeout() +{ + auto plugin = getLevel2LoginPlugin(); + if (!plugin) { + return DEFAULT_SESSION_TIMEOUT; + } + return plugin->sessionTimeout(); +} + +bool LPUtil::hasSecondLevel(const QString &user) +{ + auto plugin = getLevel2LoginPlugin(); + if (!plugin) { + return false; + } + return plugin->hasSecondLevel(user); +} + +LoginPlugin* LPUtil::getLevel2LoginPlugin() +{ + const auto &plugins = PluginManager::instance()->getLoginPlugins(2); + return plugins.empty() ? nullptr : plugins.first(); +} diff --git a/src/global_util/plugin_manager/login_plugin_util.h b/src/global_util/plugin_manager/login_plugin_util.h new file mode 100644 index 00000000..44f28064 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_util.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef LOGIN_PLUGIN_UTIL_H +#define LOGIN_PLUGIN_UTIL_H + +#include "login_plugin.h" + +class LPUtil +{ +public: + using Type = LoginPlugin::CustomLoginType; + + static int loginType(); + static int updateLoginType(); + static int sessionTimeout(); + static bool hasSecondLevel(const QString &user); + static LoginPlugin* getLevel2LoginPlugin(); +}; + + +#endif //LOGIN_PLUGIN_UTIL_H diff --git a/src/global_util/plugin_manager/login_plugin_v1.cpp b/src/global_util/plugin_manager/login_plugin_v1.cpp new file mode 100644 index 00000000..a1a60541 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_v1.cpp @@ -0,0 +1,124 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "login_plugin_v1.h" + +#include + +namespace LoginPlugin_V1 { + +#define TO_LOGIN_PLUGIN \ + dss::module::LoginModuleInterface* loginPlugin = dynamic_cast(m_plugin); + +LoginPlugin::AuthCallbackFun LoginPluginV1::authCallbackFunc = nullptr; +PluginBase::MessageCallbackFunc LoginPluginV1::messageCallbackFunc = nullptr; + +LoginPluginV1::LoginPluginV1(dss::module::LoginModuleInterface* module, QObject *parent) + : LoginPlugin(module, parent) +{ + +} + +PluginBase::ModuleType LoginPluginV1::type() const +{ + TO_LOGIN_PLUGIN + + if (!loginPlugin) + return ModuleType::LoginType; + + return m_plugin->type(); +} + +QString LoginPluginV1::icon() const +{ + TO_LOGIN_PLUGIN + + if (!loginPlugin) + return ""; + + return QString::fromStdString(loginPlugin->icon()); +} + +void LoginPluginV1::setMessageCallback(MessageCallbackFunc func) +{ + messageCallbackFunc = func; + m_loginCallBack.messageCallbackFunc = &LoginPluginV1::messageCallBack; +} + +void LoginPluginV1::setAppData(AppDataPtr func) +{ + m_loginCallBack.app_data = func; +} + +QString LoginPluginV1::message(const QString & msg) +{ + TO_LOGIN_PLUGIN + + if (!loginPlugin) + return ""; + + return QString::fromStdString(loginPlugin->onMessage(msg.toStdString())); +} + +void LoginPluginV1::setAuthCallback(LoginPlugin::AuthCallbackFun func) +{ + TO_LOGIN_PLUGIN + + authCallbackFunc = func; + m_loginCallBack.authCallbackFun = &LoginPluginV1::authCallBack; + if (!m_loginCallBack.authCallbackFun || !m_loginCallBack.app_data) { + qCWarning(DDE_SHELL) << "Auth callback funtion or app data is null"; + } + + loginPlugin->setCallback(&m_loginCallBack); +} + +void LoginPluginV1::reset() +{ + TO_LOGIN_PLUGIN + + if (!loginPlugin) + return; + + return loginPlugin->reset(); +} + +void LoginPluginV1::authCallBack(const dss::module::AuthCallbackData *authData, void *appData) +{ + if (!authCallbackFunc) { + qCWarning(DDE_SHELL) << "Authentication call back function is null"; + return; + } + + if (!appData) { + qCWarning(DDE_SHELL) << "App data is nullptr"; + return; + } + + LoginPlugin::AuthCallbackData authDataV2; + authDataV2.account = QString::fromStdString(authData->account); + authDataV2.token = QString::fromStdString(authData->token); + authDataV2.result = authData->result; + authDataV2.message = QString::fromStdString(authData->message); + authDataV2.json = QString::fromStdString(authData->json); + + authCallbackFunc(&authDataV2, appData); +} + +std::string LoginPluginV1::messageCallBack(const std::string & message, void *appData) +{ + if (!messageCallbackFunc) { + qCWarning(DDE_SHELL) << "Message callback function pointer is nullptr"; + return ""; + } + + if (!appData) { + qCWarning(DDE_SHELL) << "Appdata is nullptr"; + return ""; + } + + const QString &ret = messageCallbackFunc(QString::fromStdString(message), appData); + return ret.toStdString(); +} + +} // namespace LoginPlugin_V1 diff --git a/src/global_util/plugin_manager/login_plugin_v1.h b/src/global_util/plugin_manager/login_plugin_v1.h new file mode 100644 index 00000000..f3d398d4 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_v1.h @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef LOGIN_PLUGIN_V1_H +#define LOGIN_PLUGIN_V1_H + +#include "login_module_interface.h" +#include "login_plugin.h" + +#include + +namespace LoginPlugin_V1 { + +const QString API_VERSION = "1.1.0"; + +class LoginPluginV1 : public LoginPlugin +{ + Q_OBJECT +public: + explicit LoginPluginV1(dss::module::LoginModuleInterface* module, QObject *parent = nullptr); + + virtual PluginBase::ModuleType type() const override; + + virtual QString icon() const override; + + virtual void setMessageCallback(MessageCallbackFunc) override; + + virtual void setAppData(AppDataPtr) override; + + virtual QString message(const QString &) override; + + virtual void setAuthCallback(LoginPlugin::AuthCallbackFun) override; + + virtual void reset() override; + + static void authCallBack(const dss::module::AuthCallbackData *, void *); + + static std::string messageCallBack(const std::string &, void *); + +private: + dss::module::LoginCallBack m_loginCallBack; + static LoginPlugin::AuthCallbackFun authCallbackFunc; + static MessageCallbackFunc messageCallbackFunc; +}; + +} // namespace LoginPlugin_V1 + +#endif // LOGIN_PLUGIN_V1_H diff --git a/src/global_util/plugin_manager/login_plugin_v2.cpp b/src/global_util/plugin_manager/login_plugin_v2.cpp new file mode 100644 index 00000000..734b6c95 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_v2.cpp @@ -0,0 +1,87 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "login_plugin_v2.h" + +namespace LoginPlugin_V2 { + +#define TO_LOGIN_PLUGIN_V2 \ + dss::module_v2::LoginModuleInterfaceV2* pluginV2 = dynamic_cast(m_plugin); + +LoginPluginV2::LoginPluginV2(dss::module_v2::LoginModuleInterfaceV2 * module, QObject *parent) + : LoginPlugin(module, parent) +{ + +} + +PluginBase::ModuleType LoginPluginV2::type() const +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return ModuleType::LoginType; + + return m_plugin->type(); +} + +QString LoginPluginV2::icon() const +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return ""; + + return pluginV2->icon(); +} + +void LoginPluginV2::setMessageCallback(MessageCallbackFunc func) +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return; + + return pluginV2->setMessageCallback(func); +} + +void LoginPluginV2::setAppData(void* func) +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return; + + return pluginV2->setAppData(func); +} + +QString LoginPluginV2::message(const QString & msg) +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return ""; + + return pluginV2->message(msg); +} + +void LoginPluginV2::setAuthCallback(AuthCallbackFun func) +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return; + + pluginV2->setAuthCallback(func); +} + +void LoginPluginV2::reset() +{ + TO_LOGIN_PLUGIN_V2 + + if (!pluginV2) + return; + + return pluginV2->reset(); +} + +} // namespace LoginPlugin_V2 diff --git a/src/global_util/plugin_manager/login_plugin_v2.h b/src/global_util/plugin_manager/login_plugin_v2.h new file mode 100644 index 00000000..420b06c0 --- /dev/null +++ b/src/global_util/plugin_manager/login_plugin_v2.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef LOGIN_PLUGIN_V2_H +#define LOGIN_PLUGIN_V2_H + +#include "login_plugin.h" +#include "login_module_interface_v2.h" + +#include + +namespace LoginPlugin_V2 { + +const QString API_VERSION = "2.0.0"; + +class LoginPluginV2 : public LoginPlugin +{ + Q_OBJECT +public: + explicit LoginPluginV2(dss::module_v2::LoginModuleInterfaceV2 *module, QObject *parent = nullptr); + + virtual PluginBase::ModuleType type() const override; + + virtual QString icon() const override; + + virtual void setMessageCallback(MessageCallbackFunc) override; + + virtual void setAppData(void*) override; + + virtual QString message(const QString &) override; + + virtual void setAuthCallback(AuthCallbackFun) override; + + virtual void reset() override; +}; + +} // namespace LoginPlugin_V2 + +#endif // LOGIN_PLUGIN_V2_H diff --git a/src/global_util/plugin_manager/modules_loader.cpp b/src/global_util/plugin_manager/modules_loader.cpp new file mode 100644 index 00000000..bb97f0a2 --- /dev/null +++ b/src/global_util/plugin_manager/modules_loader.cpp @@ -0,0 +1,386 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "modules_loader.h" +#include "base_module_interface.h" +#include "dconfig_helper.h" +#include "plugin_manager.h" +#include "public_func.h" + +#include +#include +#include +#include +#include + +#include + +const QString ModulesDir = "/usr/lib/dde-session-shell/modules"; +const QString ModulesConfigDir = "/usr/lib/dde-session-shell/modules/config.d/"; +const QString LOWEST_VERSION = "1.1.0"; +const QString LoginType = "Login"; +const QString TrayType = "Tray"; + +ModulesLoader::ModulesLoader(QObject* parent) + : QThread(parent) + , m_loadLoginModule(false) + , m_model(nullptr) +{ +} + +ModulesLoader::~ModulesLoader() +{ + quit(); + wait(); + + QMutexLocker locker(&m_mutex); + for (auto &loader : m_pluginLoaders) { + cleanupPluginLoader(loader); + } + m_pluginLoaders.clear(); +} + +ModulesLoader& ModulesLoader::instance() +{ + static ModulesLoader modulesLoader; + return modulesLoader; +} + +void ModulesLoader::run() +{ + findModule(ModulesDir); +} + +void ModulesLoader::findModule(const QString& path) +{ + QDir dir(path); + if (!dir.exists()) { + qCDebug(DDE_SHELL) << "Find module, Path: " << path << "is not exists."; + return; + } + + auto blackList = DConfigHelper::instance()->getConfig("pluginBlackList", QStringList()).toStringList(); + qCInfo(DDE_SHELL) << "Find module, plugin black list:" << blackList; + const QFileInfoList modules = dir.entryInfoList(); + for (QFileInfo module : modules) { + const QString path = module.absoluteFilePath(); + if (!QLibrary::isLibrary(path)) { + continue; + } + + // 检查是否要加载插件 + if (!isPluginEnabled(module)) { + qCInfo(DDE_SHELL) << "The plugin dose not want to be loaded, path:" << path; + // Unload 后再次加载插件会导致插件不显示,且 unload不会降低内存,意义不大 + // QMetaObject::invokeMethod(this, "unloadPlugin", Qt::QueuedConnection, Q_ARG(QString, path)); + continue; + } + + // 避免重复加载 + if (contains(path)) { + qCInfo(DDE_SHELL) << "The plugin has been loaded, path:" << path; + continue; + } + + qCInfo(DDE_SHELL) << "About to process " << module; + auto loader = std::unique_ptr(new QPluginLoader(path)); + + // 检查兼容性 + const QJsonObject meta = loader->metaData().value("MetaData").toObject(); + const QString version = meta.value("api").toString(); + // 版本过低则不加载,可能会导致登录器崩溃 + if (!checkVersion(version, LOWEST_VERSION)) { + qCWarning(DDE_SHELL) << "The module version is too low, version:" << version << ", lowest version:" << LOWEST_VERSION; + continue; + } + + // 性能优化,分类加载 + QString pluginType = meta.value("pluginType").toString(); + if (!pluginType.isEmpty()) { + if ((pluginType == LoginType && !m_loadLoginModule) || (pluginType == TrayType && m_loadLoginModule)) { + continue; + } + } else { + // (兼容)没有pluginType的插件在第一次加载插件的时候就加载 + qCInfo(DDE_SHELL) << "Old plugin has no pluginType in json file:" << module; + } + + auto* moduleInstance = dynamic_cast(loader->instance()); + if (!moduleInstance) { + qCWarning(DDE_SHELL) << "Load plugin failed, error:" << loader->errorString(); + loader->unload(); + continue; + } + + qCInfo(DDE_SHELL) << "Current plugin key:" << moduleInstance->key(); + if (blackList.contains(moduleInstance->key())) { + qCInfo(DDE_SHELL) << "The plugin is in black list, won't be loaded."; + loader->unload(); + continue; + } + + int loadPluginType = moduleInstance->loadPluginType(); + if (loadPluginType != dss::module::BaseModuleInterface::Load) { + qCInfo(DDE_SHELL) << "The plugin dose not want to be loaded."; + loader->unload(); + continue; + } + + if (PluginManager::instance()->contains(moduleInstance->key())) { + qCInfo(DDE_SHELL) << "The plugin has been loaded."; + loader->unload(); + continue; + } + + QObject* obj = dynamic_cast(moduleInstance); + if (obj) + obj->moveToThread(qApp->thread()); + if (loader) + loader->moveToThread(qApp->thread()); + + QMutexLocker locker(&m_mutex); + m_pluginLoaders.insert(moduleInstance->key(), QPointer(loader.get())); + loader.release(); // 释放所有权,防止 QPluginLoader 被析构 + PluginManager::instance()->addPlugin(moduleInstance, version); + } + m_loadLoginModule = true; + Q_EMIT loadPluginsFinished(); +} + +/** + * @brief 获取插件是否需要被加载,在插件被 load 之前就可以判断,默认返回 true + * 从 /usr/lib/dde-session-shell/modules/config.d 文件夹中获取和插件同名(去掉lib后)的 json 文件,从 json 文件中获取 dconfig 的配置信息 + * json 文件示例: + * "pluginEnabled": { + * "lock": { + * "dbusProperty": { + * "service": "com.deepin.daemon.Accounts", + * "path": "/com/deepin/daemon/Accounts/User%{uid}", + * "interface": "com.deepin.daemon.Accounts.User", + * "dbusConnection": "systembus", + * "property": "WeChatAuthEnabled" + * } + * }, + * "greeter": { + * "shell": "/usr/bin/check-wechat-auth-enabled.sh" + * }, + * } + * `lock`字段表明这个配置适用于锁屏界面;`greeter`字段表明这个配置适用于登录界面 + * `dbusProperty`字段表明需要通过 dbus 获取属性,并且可以监听属性变化;`shell`字段表明是一个 shell 命令,执行命令获取返回值,0 是加载,其它不加载。 + * + * 另外还支持 dconfig 类型,例如: + * + * { + * "pluginEnabled": { + * "lock": { + * "dconfig": { + * "appid": "org.deepin.dde.lock", + * "resource": "org.deepin.dde.dss-qrcode-auth-plugin", + * "subpath": "", + * "key": "qrcodeAuthEnabled" + * } + * } + * } + * `qrcodeAuthEnabled`是一个 bool 类型的 dconfig,程序监听 qrcodeAuthEnabled 配置的变化,动态加载/卸载插件 + + * + * @param module 插件文件信息 + * @return true 需要被加载 + * @return false 不需要被加载 + */ +bool ModulesLoader::isPluginEnabled(const QFileInfo& module) +{ + QString configFileName = module.baseName(); + if (configFileName.startsWith("lib")) { + configFileName = configFileName.right(configFileName.length() - 3); + } + const QString configFile = ModulesConfigDir + configFileName + ".json"; + if (!QFile::exists(configFile)) + return true; + + qCInfo(DDE_SHELL) << "Find module config file:" << configFile; + QFile f(configFile); + if (!f.open(QIODevice::ReadOnly)) { + qCWarning(DDE_SHELL) << "Open module config file failed."; + return true; + } + + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(f.readAll(), &parseError); + f.close(); + if (doc.isNull() || parseError.error != QJsonParseError::NoError) { + qCWarning(DDE_SHELL) << "Parse module config file failed, error:" << parseError.errorString(); + return true; + } + + // 执行到下面的阶段,那么认定插件是必须要通过判断后才能加载的,一旦出现异常则不加载插件 + const auto& obj = doc.object(); + if (obj.contains("pluginEnabled")) { + const auto& enabledObj = obj.value("pluginEnabled").toObject(); + if (enabledObj.isEmpty()) { + qCWarning(DDE_SHELL) << "Check load state is not valid."; + return false; + } + qCDebug(DDE_SHELL) << "Plugin enabled object:" << enabledObj; + const auto appType = qApp->property("dssAppType").toInt(); + QString configField = appType == APP_TYPE_LOCK ? "lock" : "greeter"; + qCDebug(DDE_SHELL) << "configField:" << configField; + if (!enabledObj.contains(configField)) { + configField = "all"; + if (!enabledObj.contains(configField)) { + qCWarning(DDE_SHELL) << "Do not exist valid field, can not get plugin enabled state."; + return false; + } + } + const auto &detailObj = enabledObj.value(configField).toObject(); + if (detailObj.contains("dconfig")) { + // 通过 dconfig 检查插件是否可以加载 + const auto &dconfigObj = detailObj.value("dconfig").toObject(); + const auto& appid = dconfigObj.value("appid").toString(); + const auto& resource = dconfigObj.value("resource").toString(); + const auto& subpath = dconfigObj.value("subpath").toString(); + const auto& key = dconfigObj.value("key").toString(); + qCInfo(DDE_SHELL) << "Check load state appid:" << appid << ", resource:" << resource << ", subpath:" << subpath << ", key:" << key; + if (appid.isEmpty() || resource.isEmpty() || key.isEmpty()) { + qCWarning(DDE_SHELL) << "Check load state is not valid."; + return false; + } + if (appType == APP_TYPE_LOCK) { + DConfigHelper::instance()->bind(appid, resource, subpath, this, key, &ModulesLoader::onDConfigPropertyChanged); + } + const bool pluginEnabled = DConfigHelper::instance()->getConfig(appid, resource, subpath, key, true).toBool(); + qCInfo(DDE_SHELL) << "Plugin is enabled:" << pluginEnabled; + return pluginEnabled; + } else if (detailObj.contains("dbusProperty")){ + // 通过 dbusProperty 检查插件是否可以加载 + const auto &dbusPropertyObj = detailObj.value("dbusProperty").toObject(); + const auto& service = dbusPropertyObj.value("service").toString(); + const auto& path = dbusPropertyObj.value("path").toString(); + const auto& interface = dbusPropertyObj.value("interface").toString(); + const auto& property = dbusPropertyObj.value("property").toString(); + qCInfo(DDE_SHELL) << "Check plugin enabled service:" << service << ", path:" << path << ", interface:" << interface << ", property:" << property; + if (service.isEmpty() || path.isEmpty() || interface.isEmpty() || property.isEmpty()) { + qCWarning(DDE_SHELL) << "Check plugin enabled service is not valid."; + return false; + } + QString targetPath = path; + + // 目前仅在 lock 中需要做这个处理 + if (targetPath.contains("%{uid}") && appType == APP_TYPE_LOCK) { + targetPath = targetPath.replace("%{uid}", QString::number(static_cast(getuid()))); + qCInfo(DDE_SHELL) << "Check plugin enabled targetPath:" << targetPath; + } + auto dbusConnection = dbusPropertyObj.value("dbusConnection").toString() == "systembus" ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); + auto dbusInterface = new QDBusInterface(service, targetPath, interface, dbusConnection); + if (!dbusInterface || !dbusInterface->isValid()) { + qCWarning(DDE_SHELL) << "Check plugin enabled dbus interface is not valid."; + dbusInterface->deleteLater(); + return false; + } + const bool pluginEnabled = dbusInterface->property(property.toStdString().c_str()).toBool(); + dbusInterface->deleteLater(); + qCInfo(DDE_SHELL) << "Plugin is enabled:" << pluginEnabled; + // 监听属性变化 + if (appType == APP_TYPE_LOCK) { + dbusConnection.connect( + service, + targetPath, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + this, + SLOT(onDbusPropertiesChanged(QString, QVariantMap, QStringList))); + m_dbusInfo.insert(interface, property); + } + return pluginEnabled; + + } else if (detailObj.contains("shell")) { + const auto &cmd = detailObj.value("shell").toString(); + qCInfo(DDE_SHELL) << "Check plugin enabled shell:" << cmd; + if (cmd.isEmpty()) { + qCWarning(DDE_SHELL) << "Check plugin enabled shell is empty"; + return false; + } + QProcess process; + process.start(cmd); + if (!process.waitForFinished()) { + qCWarning(DDE_SHELL) << "Execute shell timeout"; + return false; + } + const int exitCode = process.exitCode(); + qCInfo(DDE_SHELL) << "Execute shell ret:" << exitCode; + return exitCode == 0; + } + } + return true; +} + +bool ModulesLoader::contains(const QString& pluginFile) const +{ + QMutexLocker locker(&m_mutex); + for (const auto& loader : m_pluginLoaders.values()) { + if (loader && loader->fileName() == pluginFile) { + return true; + } + } + return false; +} + +QPair ModulesLoader::getPluginLoader(const QString& pluginFile) const +{ + QMutexLocker locker(&m_mutex); + auto it = m_pluginLoaders.begin(); + for (; it != m_pluginLoaders.end(); it++) { + const auto loader = it.value(); + if (loader && loader->fileName() == pluginFile) { + return qMakePair(it.key(), loader); + } + } + return qMakePair(QString(), nullptr); +} + +void ModulesLoader::unloadPlugin(const QString& path) +{ + if (contains(path)) { + auto pair = getPluginLoader(path); + if (!pair.first.isEmpty() && pair.second) { + qCInfo(DDE_SHELL) << "Remove plugin: " << pair.first; + PluginManager::instance()->removePlugin(pair.first); + QMutexLocker locker(&m_mutex); + m_pluginLoaders.remove(pair.first); + qCInfo(DDE_SHELL) << "Unload plugin loader"; + pair.second->unload(); + } + } +} + +void ModulesLoader::cleanupPluginLoader(QPluginLoader* loader) +{ + if (loader) { + loader->unload(); + loader->deleteLater(); + } +} + +// TODO 只重新加载/卸载变更的插件 +void ModulesLoader::onDConfigPropertyChanged(const QString& key, const QVariant& value, QObject* objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + qCInfo(DDE_SHELL) << "DConfig property changed, key: " << key << ", value: " << value; + obj->start(QThread::LowestPriority); +} + +void ModulesLoader::onDbusPropertiesChanged(const QString& interfaceName, const QVariantMap& changedProperties, const QStringList& invalidatedProperties) +{ + Q_UNUSED(invalidatedProperties) + qCDebug(DDE_SHELL) << "Dbus properties changed, interface: " << interfaceName << ", changed properties: " << changedProperties; + if (m_dbusInfo.contains(interfaceName)) { + const auto &property = m_dbusInfo.value(interfaceName); + if (changedProperties.contains(property)) { + start(QThread::LowestPriority); + } + } +} diff --git a/src/global_util/plugin_manager/modules_loader.h b/src/global_util/plugin_manager/modules_loader.h new file mode 100644 index 00000000..504024fd --- /dev/null +++ b/src/global_util/plugin_manager/modules_loader.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef MODULES_LOADER_H +#define MODULES_LOADER_H + +#include "sessionbasemodel.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class ModulesLoader : public QThread +{ + Q_OBJECT +public: + static ModulesLoader &instance(); + void setLoadLoginModule(bool loadLoginModule) { m_loadLoginModule = loadLoginModule; } + void setModel(SessionBaseModel *model); + +signals: + void loadPluginsFinished(); + +protected: + void run() override; + +private: + explicit ModulesLoader(QObject *parent = nullptr); + ~ModulesLoader() override; + ModulesLoader(const ModulesLoader &) = delete; + ModulesLoader &operator=(const ModulesLoader &) = delete; + + void findModule(const QString &path); + bool isPluginEnabled(const QFileInfo &module); + bool contains(const QString &pluginFile) const; + QPair getPluginLoader(const QString &pluginFile) const; + void cleanupPluginLoader(QPluginLoader* loader); + + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); + +private Q_SLOTS: + void unloadPlugin(const QString &path); + void onDbusPropertiesChanged(const QString& interfaceName, + const QVariantMap& changedProperties, + const QStringList& invalidatedProperties); + +private: + bool m_loadLoginModule; + QMap> m_pluginLoaders; + QMap m_dbusInfo; + mutable QMutex m_mutex; + QPointer m_model; +}; + +#endif // MODULES_LOADER_H diff --git a/src/global_util/plugin_manager/plugin_base.cpp b/src/global_util/plugin_manager/plugin_base.cpp new file mode 100644 index 00000000..a4c89cf4 --- /dev/null +++ b/src/global_util/plugin_manager/plugin_base.cpp @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_base.h" + +PluginBase::PluginBase(dss::module::BaseModuleInterface* module, QObject *parent) + : QObject(parent) + , m_plugin(module) +{ + +} + +void PluginBase::init() +{ + if (!m_plugin) + return; + + m_plugin->init(); +} + +QString PluginBase::key() const +{ + if (!m_plugin) + return ""; + + return m_plugin->key(); +} + +QWidget *PluginBase::content() +{ + if (!m_plugin) + return nullptr; + + return m_plugin->content(); +} + +PluginBase::LoadType PluginBase::loadPluginType() +{ + if (!m_plugin) + return LoadType::Notload; + + return m_plugin->loadPluginType(); +} + +QJsonObject PluginBase::getRootObj(const QString &jsonStr) +{ + QJsonParseError jsonParseError; + const QJsonDocument &resultDoc = QJsonDocument::fromJson(jsonStr.toLocal8Bit(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || resultDoc.isEmpty()) { + qCWarning(DDE_SHELL) << "Result json parse error, error: " << jsonParseError.error; + return QJsonObject(); + } + + return resultDoc.object(); +} + +QJsonObject PluginBase::getDataObj(const QString &jsonStr) +{ + const QJsonObject &rootObj = getRootObj(jsonStr); + if (!rootObj.contains("Data")) { + qCWarning(DDE_SHELL) << "Result doesn't contains the 'data' field"; + return QJsonObject(); + } + + return rootObj["Data"].toObject(); +} diff --git a/src/global_util/plugin_manager/plugin_base.h b/src/global_util/plugin_manager/plugin_base.h new file mode 100644 index 00000000..3e351ef7 --- /dev/null +++ b/src/global_util/plugin_manager/plugin_base.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PLUGIN_BASE_H +#define PLUGIN_BASE_H + +#include "constants.h" +#include "base_module_interface.h" + +#include +#include + +class PluginBase : public QObject +{ + Q_OBJECT +public: + using ModuleType = dss::module::BaseModuleInterface::ModuleType; + using LoadType = dss::module::BaseModuleInterface::LoadType; + using AppDataPtr = dss::module::AppDataPtr; + using MessageCallbackFunc = dss::module::MessageCallbackFunc; + + explicit PluginBase(dss::module::BaseModuleInterface* module, QObject *parent = nullptr); + + virtual ModuleType type() const = 0; + + virtual void init(); + + virtual QString key() const; + + virtual QString icon() const { return ""; } + + virtual QWidget *content(); + + virtual LoadType loadPluginType(); + + virtual void setMessageCallback(MessageCallbackFunc func) {} + + virtual void setAppData(void*) {} + + virtual QString message(const QString &) { return ""; } + + static QJsonObject getRootObj(const QString &jsonStr); + + static QJsonObject getDataObj(const QString &jsonStr); + +protected: + dss::module::BaseModuleInterface *m_plugin; +}; + +#endif // PLUGIN_BASE_H diff --git a/src/global_util/plugin_manager/plugin_manager.cpp b/src/global_util/plugin_manager/plugin_manager.cpp new file mode 100644 index 00000000..82c1b4e7 --- /dev/null +++ b/src/global_util/plugin_manager/plugin_manager.cpp @@ -0,0 +1,320 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "plugin_manager.h" +#include "constants.h" +#include "dconfig_helper.h" +#include "login_plugin_v1.h" +#include "login_plugin_v2.h" +#include "public_func.h" +#include "modules_loader.h" + +static PluginManager pluginManager; + +PluginManager::PluginManager(QObject* parent) + : QObject(parent) +{ + // 有些插件需要通过 MessageCallback 获取信息来判断自己是否要被启用,但是 CustomAuth 需要判断为被启用后才会被创建,这里有冲突 + // TODO MessageCallback 应该走 PluginManager,而不是CustomAuth + connect(&ModulesLoader::instance(), &ModulesLoader::loadPluginsFinished, this, &PluginManager::broadcastCurrentUser); +} + +PluginManager* PluginManager::instance() +{ + return &pluginManager; +} + +void PluginManager::addPlugin(dss::module::BaseModuleInterface* module, const QString& version) +{ + if (!module) { + qCWarning(DDE_SHELL) << "Module is null."; + return; + } + + qCInfo(DDE_SHELL) << "Add plugin:" << module->key() << ", version:" << version; + PluginBase* plugin = createPlugin(module, version); + if (!plugin) { + qCWarning(DDE_SHELL) << "Create plugin failed."; + return; + } + + const QString& key = plugin->key(); + m_plugins.insert(key, plugin); + connect(plugin, &QObject::destroyed, this, [this, key] { + qCInfo(DDE_SHELL) << key << " was destroyed."; + m_plugins.remove(key); + }); +} + +void PluginManager::removePlugin(const QString &key) +{ + qCInfo(DDE_SHELL) << "Remove plugin:" << key; + auto it = m_plugins.find(key); + if (it == m_plugins.end()) { + qCWarning(DDE_SHELL) << "Plugin not found:" << key; + return; + } + Q_EMIT pluginAboutToBeRemoved(key); + if (it.value()) + it.value()->deleteLater(); + m_plugins.remove(key); +} + + +/** + * @brief 获取登录插件 + * + * @param level 登录插件级别,1 为普通插件,2 为域管二级插件 + * @return QList + */ +QList PluginManager::getLoginPlugins(int level) const +{ + // 指定插件 >> 默认插件 + const auto& designatedLoginPlugin = DConfigHelper::instance()->getConfig("designatedLoginPlugin", "").toString(); + const auto& defaultLoginPlugin = DConfigHelper::instance()->getConfig("defaultLoginPlugin", "").toString(); + auto designatedLoginPlugins = DConfigHelper::instance()->getConfig("designatedLoginPlugins", QStringList()).toStringList(); + auto defaultLoginPlugins = DConfigHelper::instance()->getConfig("defaultLoginPlugins", QStringList()).toStringList(); + qCInfo(DDE_SHELL) << "Designated login plugin:" << designatedLoginPlugin + << "Default login plugins" << defaultLoginPlugin + << "Designated login plugins:" << designatedLoginPlugins + << "Default login plugins:" << defaultLoginPlugins; + + if (!designatedLoginPlugin.isEmpty()) + designatedLoginPlugins.append(designatedLoginPlugin); + if (!defaultLoginPlugin.isEmpty()) + defaultLoginPlugins.append(defaultLoginPlugin); + const auto& finalPlugins = !designatedLoginPlugins.isEmpty() ? designatedLoginPlugins : defaultLoginPlugins; + qCInfo(DDE_SHELL) << "Final login plugins:" << finalPlugins; + qCInfo(DDE_SHELL) << "All plugins:" << m_plugins.keys(); + QMap map; + for (const auto& plugin : m_plugins.values()) { + if (plugin && PluginBase::ModuleType::LoginType == plugin->type()) { + if (!finalPlugins.isEmpty() && !finalPlugins.contains(plugin->key())) + continue; + + auto authPlugin = dynamic_cast(plugin); + if (authPlugin && authPlugin->level() == level) + map.insert(authPlugin->key(), authPlugin); + } + } + + // 根据配置排序 + QList list; + const auto& order = DConfigHelper::instance()->getConfig(DDESESSIONCC::LOGIN_PLUGIN_DISPLAY_ORDER, {}).toStringList(); + qCInfo(DDE_SHELL) << "Login plugin display order:" << order; + for (const auto& key : order) { + const auto plugin = map.take(key); + if (plugin) + list.append(plugin); + } + list.append(map.values()); + return list; +} + +LoginPlugin* PluginManager::getFullManagedLoginPlugin() const +{ + for (const auto& plugin : m_plugins.values()) { + if (plugin && PluginBase::ModuleType::FullManagedLoginType == plugin->type()) { + return dynamic_cast(plugin); + } + } + + return nullptr; +} + +LoginPlugin *PluginManager::getLoginPlugin(int authType) const +{ + for (const auto &plugin : m_plugins.values()) { + if (plugin && PluginBase::ModuleType::LoginType == plugin->type()) { + auto p = dynamic_cast(plugin); + p->updateConfig(); + if (p->defaultAuthType() == authType) { + return p; + } + } + } + + qDebug() << "plugin for type " << authType << "not found in " << m_plugins; + + return nullptr; +} + +QList PluginManager::trayPlugins() const +{ + QList list; + for (const auto& plugin : m_plugins.values()) { + if (plugin && PluginBase::ModuleType::TrayType == plugin->type()) { + list.append(dynamic_cast(plugin)); + } + } + + return list; +} + +PluginBase* PluginManager::createPlugin(dss::module::BaseModuleInterface* module, const QString& version) +{ + if (dss::module::BaseModuleInterface::LoginType == module->type() + || dss::module::BaseModuleInterface::FullManagedLoginType == module->type() + || dss::module::BaseModuleInterface::IpcAssistLoginType == module->type() + || dss::module::BaseModuleInterface::PasswordExtendLoginType == module->type()) { + return createLoginPlugin(module, version); + } else if (dss::module::BaseModuleInterface::TrayType == module->type()) { + TrayPlugin* plugin = createTrayPlugin(module, version); + trayPluginAdded(plugin); + return plugin; + } + + qCWarning(DDE_SHELL) << "This plug-in type is not recognized: " << module->type(); + return nullptr; +} + +LoginPlugin* PluginManager::createLoginPlugin(dss::module::BaseModuleInterface* module, const QString& version) +{ + qCInfo(DDE_SHELL) << "Create login plugin, meta version: " << version; + if (checkVersion(version, LoginPlugin_V2::API_VERSION)) { + qCInfo(DDE_SHELL) << "Create LoginPluginV2"; + return new LoginPlugin_V2::LoginPluginV2(dynamic_cast(module)); + } else if (checkVersion(version, LoginPlugin_V1::API_VERSION)) { + qCInfo(DDE_SHELL) << "Create LoginPluginV1"; + return new LoginPlugin_V1::LoginPluginV1(dynamic_cast(module)); + } + + return nullptr; +} + +TrayPlugin* PluginManager::createTrayPlugin(dss::module::BaseModuleInterface* module, const QString& version) +{ + Q_UNUSED(version) + + return new TrayPlugin(dynamic_cast(module)); +} + +bool PluginManager::contains(const QString& key) const +{ + return m_plugins.contains(key); +} + +PluginBase* PluginManager::findPlugin(const QString& key) const +{ + if (!m_plugins.contains(key)) + return nullptr; + + return m_plugins.value(key); +} + +LoginPlugin* PluginManager::getAssistloginPlugin() const +{ + for (const auto& plugin : m_plugins.values()) { + if (plugin && PluginBase::ModuleType::IpcAssistLoginType == plugin->type()) { + return dynamic_cast(plugin); + } + } + + return nullptr; +} + +LoginPlugin *PluginManager::getFirstLoginPlugin(PluginBase::ModuleType type) const +{ + for (const auto& plugin : m_plugins.values()) { + if (plugin && type == plugin->type()) { + return dynamic_cast(plugin); + } + } + + return nullptr; +} + +void PluginManager::setModel(SessionBaseModel *model) +{ + if (!model) + return; + + m_model = model; + + connect(m_model, &SessionBaseModel::currentUserChanged, this, &PluginManager::broadcastCurrentUser); + broadcastCurrentUser(); +} + +void PluginManager::broadcastCurrentUser() +{ + if (!m_model) + return; + + const auto ¤tUser = m_model->currentUser(); + if (!currentUser) + return; + + for (const auto &plugin : m_plugins.values()) { + auto loginPlugin = dynamic_cast(plugin); + if (!loginPlugin) + continue; + + loginPlugin->notifyCurrentUserChanged(currentUser->name(), currentUser->uid()); + } +} + +void PluginManager::broadcastAuthFactors(int authFactors) +{ + for (const auto &plugin : m_plugins.values()) { + auto loginPlugin = dynamic_cast(plugin); + if (!loginPlugin) + continue; + + loginPlugin->notifyAuthFactorsChanged(authFactors); + } +} + +QPair PluginManager::parseMessage(const QString &message) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + QJsonObject retObj; + QJsonObject dataObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + retObj["Code"] = -1; + retObj["Message"] = "Failed to analysis message info"; + qCWarning(DDE_SHELL) << "Failed to analysis message from plugin: " << message; + return qMakePair(toJson(retObj), messageDoc); + } + + return qMakePair(QStringLiteral(""), messageDoc); +} + +QString PluginManager::getProperties(const QJsonObject &messageObj) const +{ + QJsonArray properties; + properties = messageObj.value("Data").toArray(); + + QJsonObject retObj; + QJsonObject dataObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + do + { + if (m_model.isNull()) { + retObj["Code"] = -1; + retObj["Message"] = "Session base model is nullptr"; + break; + } + if (properties.contains("AppType")) { + dataObj["AppType"] = m_model->appType(); + } + if (properties.contains("CurrentUser")) { + if (m_model->currentUser()) { + QJsonObject user; + user["Name"] = m_model->currentUser()->name(); + user["Uid"] = static_cast(m_model->currentUser()->uid()); + dataObj["CurrentUser"] = user; + } else { + retObj["Code"] = -1; + retObj["Message"] = "Current user is null!"; + } + } + } while(0); + retObj["Data"] = dataObj; + + return toJson(retObj); +} diff --git a/src/global_util/plugin_manager/plugin_manager.h b/src/global_util/plugin_manager/plugin_manager.h new file mode 100644 index 00000000..76d88fe4 --- /dev/null +++ b/src/global_util/plugin_manager/plugin_manager.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PLUGIN_MANAGER_H +#define PLUGIN_MANAGER_H + +#include "base_module_interface.h" +#include "login_plugin.h" +#include "tray_plugin.h" +#include "plugin_base.h" +#include "sessionbasemodel.h" + +#include +#include + +class PluginManager : public QObject +{ + Q_OBJECT +public: + explicit PluginManager(QObject *parent = nullptr); + static PluginManager* instance(); + + void setModel(SessionBaseModel *model); + void addPlugin(dss::module::BaseModuleInterface *module, const QString &version); + void removePlugin(const QString &key); + QList getLoginPlugins(int level = 1) const; + LoginPlugin *getFullManagedLoginPlugin() const; + LoginPlugin *getAssistloginPlugin() const; + LoginPlugin *getFirstLoginPlugin(PluginBase::ModuleType type) const; + LoginPlugin *getLoginPlugin(int authType) const; + QList trayPlugins() const; + bool contains(const QString &key) const; + PluginBase *findPlugin(const QString &key) const; + void broadcastAuthFactors(int authFactors); + QString getProperties(const QJsonObject &messageObj) const; + + static QPair parseMessage(const QString &message); + +signals: + void trayPluginAdded(TrayPlugin *); + void pluginAboutToBeRemoved(const QString &key); + +private slots: + void broadcastCurrentUser(); + +private: + PluginBase* createPlugin(dss::module::BaseModuleInterface *module, const QString &version); + LoginPlugin *createLoginPlugin(dss::module::BaseModuleInterface *module, const QString &version); + TrayPlugin *createTrayPlugin(dss::module::BaseModuleInterface *module, const QString &version); + +private: + QPointer m_model; + QMap m_plugins; +}; + +#endif // PLUGIN_MANAGER_H diff --git a/src/global_util/plugin_manager/tray_plugin.cpp b/src/global_util/plugin_manager/tray_plugin.cpp new file mode 100644 index 00000000..f8d45589 --- /dev/null +++ b/src/global_util/plugin_manager/tray_plugin.cpp @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "tray_plugin.h" + +/** + * 插件统一封装,如果后面有不兼容的更新,则拆分多个版本,继承此类 + */ + +#define TO_TRAY_PLUGIN \ + dss::module::TrayModuleInterface* trayPlugin = dynamic_cast(m_plugin); + +TrayPlugin::TrayPlugin(dss::module::TrayModuleInterface *module, QObject *parent) + : PluginBase(module, parent) +{ + +} + +QString TrayPlugin::icon() const +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return ""; + + return trayPlugin->icon(); +} + +void TrayPlugin::setMessageCallback(MessageCallbackFunc func) +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return; + + return trayPlugin->setMessageCallback(func); +} + +void TrayPlugin::setAppData(void* func) +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return; + + return trayPlugin->setAppData(func); +} + +QString TrayPlugin::message(const QString & msg) +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return ""; + + return trayPlugin->message(msg); +} + +QWidget *TrayPlugin::itemWidget() const +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return nullptr; + + return trayPlugin->itemWidget(); +} + +QWidget *TrayPlugin::itemTipsWidget() const +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return nullptr; + + return trayPlugin->itemTipsWidget(); +} + +const QString TrayPlugin::itemContextMenu() const +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return nullptr; + + return trayPlugin->itemContextMenu(); +} + +void TrayPlugin::invokedMenuItem(const QString &menuId, const bool checked) const +{ + TO_TRAY_PLUGIN + + if (!trayPlugin) + return; + + trayPlugin->invokedMenuItem(menuId, checked); +} diff --git a/src/global_util/plugin_manager/tray_plugin.h b/src/global_util/plugin_manager/tray_plugin.h new file mode 100644 index 00000000..5a46fc5f --- /dev/null +++ b/src/global_util/plugin_manager/tray_plugin.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef TRAYPLUGIN_H +#define TRAYPLUGIN_H + +#include "plugin_base.h" +#include "tray_module_interface.h" + +class TrayPlugin : public PluginBase +{ + Q_OBJECT +public: + explicit TrayPlugin(dss::module::TrayModuleInterface *module, QObject *parent = nullptr); + + virtual PluginBase::ModuleType type() const { return PluginBase::ModuleType::TrayType; }; + + virtual QString icon() const; + + virtual void setMessageCallback(MessageCallbackFunc); + + virtual void setAppData(AppDataPtr); + + virtual QString message(const QString &); + + virtual QWidget *itemWidget() const; + + virtual QWidget *itemTipsWidget() const; + + virtual const QString itemContextMenu() const; + + virtual void invokedMenuItem(const QString &menuId, const bool checked) const; +}; + +#endif // TRAYPLUGIN_H diff --git a/src/global_util/public_func.cpp b/src/global_util/public_func.cpp index f4c61beb..dbddc5d9 100644 --- a/src/global_util/public_func.cpp +++ b/src/global_util/public_func.cpp @@ -1,58 +1,143 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * Hualet - * kirigaya - * - * Maintainer: sbw - * Hualet - * kirigaya - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "public_func.h" #include "constants.h" -#include - #include -#include -#include #include #include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include + +#ifndef ENABLE_DSS_SNIPE +#include +#else +#include +#endif using namespace std; DCORE_USE_NAMESPACE +Q_LOGGING_CATEGORY(DDE_SHELL, "org.deepin.dde.shell") + static int appType = APP_TYPE_LOCK; +//Load the System cursor --begin +static XcursorImages* +xcLoadImages(const char *image, int size) +{ + QSettings settings(DDESESSIONCC::DEFAULT_CURSOR_THEME, QSettings::IniFormat); + //The default cursor theme path + qDebug() << "Theme Path:" << DDESESSIONCC::DEFAULT_CURSOR_THEME; + QString item = "Icon Theme"; + const char* defaultTheme = ""; + QVariant tmpCursorTheme = settings.value(item + "/Inherits"); + if (tmpCursorTheme.isNull()) { + qDebug() << "Set a default one instead, if get the cursor theme failed!"; + defaultTheme = "Deepin"; + } else { + defaultTheme = tmpCursorTheme.toString().toLocal8Bit().data(); + } + + qDebug() << "Get defaultTheme:" << tmpCursorTheme.isNull() + << defaultTheme; + return XcursorLibraryLoadImages(image, defaultTheme, size); +} + +static unsigned long loadCursorHandle(Display *dpy, const char *name, int size) +{ + if (size == -1) { + size = XcursorGetDefaultSize(dpy); + } + + // Load the cursor images + XcursorImages *images = nullptr; + images = xcLoadImages(name, size); + + if (!images) { + images = xcLoadImages(name, size); + if (!images) { + return 0; + } + } + + unsigned long handle = static_cast(XcursorImagesLoadCursor(dpy,images)); + XcursorImagesDestroy(images); + + return handle; +} + +int setRootWindowCursor() { + Display* display = XOpenDisplay(nullptr); + if (!display) { + qCWarning(DDE_SHELL) << "Open display failed, display is empty"; + return -1; + } + + const char *cursorPath = qApp->devicePixelRatio() > 1.7 + ? "/usr/share/icons/bloom/cursors/loginspinner@2x" + : "/usr/share/icons/bloom/cursors/loginspinner"; + + Cursor cursor = static_cast(XcursorFilenameLoadCursor(display, cursorPath)); + if (cursor == 0) { + cursor = static_cast(loadCursorHandle(display, "watch", 24)); + } + XDefineCursor(display, XDefaultRootWindow(display),cursor); + + // XFixesChangeCursorByName is the key to change the cursor + // and the XFreeCursor and XCloseDisplay is also essential. + + XFixesChangeCursorByName(display, cursor, "watch"); + + XFreeCursor(display, cursor); + XCloseDisplay(display); + + return 0; +} + +// 初次启动时,设置一下鼠标的默认位置 +void setPointer() +{ + auto set_position = [ = ] (QPoint p) { + Display *dpy; + dpy = XOpenDisplay(nullptr); + + if (!dpy) return; + + Window root_window; + root_window = XRootWindow(dpy, 0); + XSelectInput(dpy, root_window, KeyReleaseMask); + XWarpPointer(dpy, None, root_window, 0, 0, 0, 0, p.x(), p.y()); + XFlush(dpy); + }; + + if (!qApp->primaryScreen()) { + QObject::connect(qApp, &QGuiApplication::primaryScreenChanged, [ = ] { + static bool first = true; + if (first) { + set_position(qApp->primaryScreen()->geometry().center()); + first = false; + } + }); + } else { + set_position(qApp->primaryScreen()->geometry().center()); + } +} + QPixmap loadPixmap(const QString &file, const QSize& size) { qreal ratio = 1.0; @@ -62,6 +147,7 @@ QPixmap loadPixmap(const QString &file, const QSize& size) if (!qFuzzyCompare(ratio, devicePixel) || size.isValid()) { QImageReader reader; + reader.setDecideFormatFromContent(true); reader.setFileName(qt_findAtNxFile(file, devicePixel, &ratio)); if (reader.canRead()) { reader.setScaledSize((size.isNull() ? reader.size() : reader.size().scaled(size, Qt::KeepAspectRatio)) * (devicePixel / ratio)); @@ -75,6 +161,38 @@ QPixmap loadPixmap(const QString &file, const QSize& size) return pixmap; } +//此处为下面函数的函数重载,用来解决Debug模式使用void loadPixmap(const QString &fileName, QPixmap &pixmap)调试崩溃问题,原因暂时不明,保险起见使用这个函数 +QPixmap loadPixmap(const QString &fileName) +{ + QPixmap pixmap; + if (!pixmap.load(fileName)) { + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + pixmap.loadFromData(file.readAll()); + } + } + + return pixmap; +} + +void loadPixmap(const QString &fileName, QPixmap &pixmap) +{ + if (!pixmap.load(fileName)) { + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + pixmap.loadFromData(file.readAll()); + } + } +} + +bool checkPictureCanRead(const QString &fileName) +{ + QImageReader reader; + reader.setDecideFormatFromContent(true); + reader.setFileName(fileName); + return reader.canRead(); +} + /** * @brief 是否使用域管认证。 * @@ -83,6 +201,7 @@ QPixmap loadPixmap(const QString &file, const QSize& size) */ bool isDeepinAuth() { +#ifndef ENABLE_DSS_SNIPE const char* controlId = "com.deepin.dde.auth.control"; if (QGSettings::isSchemaInstalled(controlId)) { const char *controlPath = "/com/deepin/dde/auth/control/"; @@ -90,66 +209,16 @@ bool isDeepinAuth() const QString &key = "useDeepinAuth"; bool useDeepinAuth = controlObj.keys().contains(key) && controlObj.get(key).toBool(); #ifdef QT_DEBUG - qDebug() << "use deepin auth: " << useDeepinAuth; + qDebug() << "Use deepin auth: " << useDeepinAuth; #endif return useDeepinAuth; } +#else + // TODO this gsetting config provided by 域管 +#endif return true; } -uint timeFromString(QString time) -{ - if (time.isEmpty()) { - return QDateTime::currentDateTime().toTime_t(); - } - return QDateTime::fromString(time, Qt::ISODateWithMs).toLocalTime().toTime_t(); -} - -/** - * @brief getDConfigValue 根据传入的\a key获取配置项的值,获取失败返回默认值 - * @param key 配置项键值 - * @param defaultValue 默认返回值,为避免出现返回值错误导致程序异常的问题,此参数必填 - * @param configFileName 配置文件名称 - * @return 配置项的值 - */ -QVariant getDConfigValue(const QString &configFileName, const QString &key, const QVariant &defaultValue) -{ - if (configFileName.isEmpty()) - return defaultValue; - - DConfig config(configFileName); - if (!config.isValid() || !config.keyList().contains(key)) { - qWarning() << "dconfig parse failed, name: " << config.name() - << "subpath: " << config.subpath() - << "\n use fallback value:" << defaultValue; - return defaultValue; - } - - return config.value(key); -} - -/** - * @brief setDConfigValue 根据传入的\a key设置对应的值 - * @param configFileName 配置文件名称 - * @param key 配置项键值 - * @param value 值 - * @return 配置项的值 - */ -void setDConfigValue(const QString &configFileName, const QString &key, const QVariant &value) -{ - if (configFileName.isEmpty()) - return; - - DConfig config(configFileName); - if (!config.isValid() || !config.keyList().contains(key)) { - qWarning() << "dconfig parse failed, name: " << config.name() - << "subpath: " << config.subpath(); - return; - } - - config.setValue(key, value); -} - void setAppType(int type) { appType = type; @@ -177,3 +246,131 @@ void loadTranslation(const QString &locale) translator.load("/usr/share/dde-session-shell/translations/dde-session-shell_" + locale.split(".").first()); qApp->installTranslator(&translator); } + +/** + * @brief findSymLinTarget 查找软连接最终链接到的文件,如果不是软连接,直接返回原始路径 + * @param symLink 文件路径 + * @return 最终链接到的文件路径 + */ +QString findSymLinTarget(const QString &symLink) +{ + QString file = symLink; + QString tmpFile = symLink; + while(!tmpFile.isEmpty()) { + file = tmpFile; + tmpFile = QFile::symLinkTarget(tmpFile); + } + + return file; +} + +/** + * @brief json对象转为json字符串 + * + * @param QJsonObject对象 + */ +QString toJson(const QJsonObject &jsonObj) +{ + QJsonDocument doc; + doc.setObject(jsonObj); + return doc.toJson(); +} + +bool checkVersion(const QString &target, const QString &base) +{ + if (target == base) { + return true; + } + const QStringList baseVersion = base.split("."); + const QStringList targetVersion = target.split("."); + + const int baseVersionSize = baseVersion.size(); + const int targetVersionSize = targetVersion.size(); + const int size = baseVersionSize < targetVersionSize ? baseVersionSize : targetVersionSize; + + for (int i = 0; i < size; i++) { + if (targetVersion[i] == baseVersion[i]) continue; + return targetVersion[i].toInt() > baseVersion[i].toInt() ? true : false; + } + return true; +} + +void configWebEngine() +{ + // 华为机型只支持OpenGLES,导致使用到webengine的地方都不能用 + // 登录锁屏用到了二维码解锁,二维码又依赖了webengine来显示 + if (qgetenv("XDG_SESSION_TYPE").contains("wayland")) { + QSurfaceFormat format; + format.setRenderableType(QSurfaceFormat::OpenGLES); + QSurfaceFormat::setDefaultFormat(format); + } + + // 禁用 qwebengine 调试功能 + qunsetenv("QTWEBENGINE_REMOTE_DEBUGGING"); + +#ifdef __sw_64__ + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox"); +#endif + + // Disable function: Qt::AA_ForceRasterWidgets, solve the display problem of domestic platform (loongson mips) + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-gpu"); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-web-security"); + qputenv("DXCB_FAKE_PLATFORM_NAME_XCB", "true"); + + //龙芯机器配置,使得DApplication能正确加载QTWEBENGINE + qputenv("DTK_FORCE_RASTER_WIDGETS", "FALSE"); + qputenv("_d_disableDBusFileDialog", "true"); + setenv("PULSE_PROP_media.role", "video", 1); + + // 使用--single-process可加快启动速度,sw 架构必须使用,否则页面加载不出来 + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--single-process"); + // FIXME 在设置了自动代理的情况下,使用--single-process会导致崩溃,暂时去掉自动代理环境变量 + const QString auto_proxy = qgetenv("auto_proxy"); + if (!auto_proxy.isEmpty()) { + qputenv("auto_proxy", ""); + } + QNetworkProxyQuery query(QUrl("https://login.uniontech.com")); + QList proxyList = QNetworkProxyFactory::systemProxyForQuery(query); + if (proxyList.size() > 0) { + QNetworkProxy::setApplicationProxy(proxyList[0]); + } +} + +#ifdef ENABLE_DSS_SNIPE +bool isSleepLock() +{ + QDBusInterface powerInterface("org.deepin.dde.Power1", + "/org/deepin/dde/Power1", "org.deepin.dde.Power1", QDBusConnection::sessionBus()); + + if (!powerInterface.isValid()) { + qCritical() << powerInterface.lastError().message(); + return true; // default + } + + QVariant value = powerInterface.property("SleepLock"); + if (!value.isValid()) { + qCritical() << "read SleepLock property failed"; + return true; // default + } + + return value.toBool(); +} +#endif + +QString qtifyName(const QString &name) { + bool next_cap = false; + QString result; + + for (auto it = name.cbegin(); it != name.cend(); ++it) { + if (*it == '-') { + next_cap = true; + } else if (next_cap) { + result.append(it->toUpper()); + next_cap = false; + } else { + result.append(*it); + } + } + + return result; +} \ No newline at end of file diff --git a/src/global_util/public_func.h b/src/global_util/public_func.h index f4e0d3a6..22a98a2a 100644 --- a/src/global_util/public_func.h +++ b/src/global_util/public_func.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PUBLIC_FUNC_H #define PUBLIC_FUNC_H @@ -35,12 +14,14 @@ #include #include -#define ACCOUNTS_DBUS_PREFIX "/com/deepin/daemon/Accounts/User" +class QJsonDocument; static const int APP_TYPE_LOCK = 0; static const int APP_TYPE_LOGIN = 1; QPixmap loadPixmap(const QString &file, const QSize& size = QSize()); +void loadPixmap(const QString &fileName, QPixmap &pixmap); +bool checkPictureCanRead(const QString &fileName); template T findValueByQSettings(const QStringList &configFiles, @@ -64,6 +45,9 @@ T findValueByQSettings(const QStringList &configFiles, return fallback.value(); } +int setRootWindowCursor(); +void setPointer(); + /** * @brief 是否使用深度认证,不使用域管认证。 * @@ -72,15 +56,6 @@ T findValueByQSettings(const QStringList &configFiles, */ bool isDeepinAuth(); -/** - * @brief 把字符串解析成时间,然后转换为Unix时间戳 - */ -uint timeFromString(QString time); - -QVariant getDConfigValue(const QString &configFileName, const QString &key, const QVariant &defaultValue); - -void setDConfigValue(const QString &configFileName, const QString &key, const QVariant &value); - /** * @brief 设置app类型,让程序知道应该获取哪个配置文件 */ @@ -92,5 +67,25 @@ void setAppType(int type); QString getDefaultConfigFileName(); void loadTranslation(const QString &locale); +QString findSymLinTarget(const QString &symLink); + +QString toJson(const QJsonObject &jsonObj); + +bool checkVersion(const QString &target, const QString &base); + +/** + * @brief 配置 qwebengine 相关环境 + */ +void configWebEngine(); + +#ifdef ENABLE_DSS_SNIPE +bool isSleepLock(); +#endif + +/** + * @brief convert 'some-key' to 'someKey'. + */ + +QString qtifyName(const QString &name); #endif // PUBLIC_FUNC_H diff --git a/src/global_util/qt-compat-helper.cpp b/src/global_util/qt-compat-helper.cpp new file mode 100644 index 00000000..e0f7b9f2 --- /dev/null +++ b/src/global_util/qt-compat-helper.cpp @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "qt-compat-helper.h" + +#include +#include + +uint QtCompatHelper::toSecsSinceEpoch(const QDateTime &dateTime) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return static_cast(dateTime.toSecsSinceEpoch()); +#else + return static_cast(dateTime.toTime_t()); +#endif +} diff --git a/src/global_util/qt-compat-helper.h b/src/global_util/qt-compat-helper.h new file mode 100644 index 00000000..9d7bc397 --- /dev/null +++ b/src/global_util/qt-compat-helper.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2021 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef QT_COMPAT_HELPER_H +#define QT_COMPAT_HELPER_H + +#include + +class QString; + +/** + * @brief Qt版本兼容性帮助类 + * + * 用于统一处理Qt5和Qt6之间的API差异,避免在代码中到处使用版本检查宏。 + * 主要解决QDateTime相关方法在不同Qt版本中的差异。 + */ +class QtCompatHelper +{ +public: + /** + * @brief 获取QDateTime对象对应的秒级时间戳 + * + * 在Qt5中使用toTime_t()方法,在Qt6中使用toSecsSinceEpoch()方法 + * + * @param dateTime QDateTime对象 + * @return uint 秒级时间戳 + */ + static uint toSecsSinceEpoch(const QDateTime &dateTime); +}; + +#endif // QT_COMPAT_HELPER_H diff --git a/src/global_util/signal_bridge.h b/src/global_util/signal_bridge.h new file mode 100644 index 00000000..0d9f33d0 --- /dev/null +++ b/src/global_util/signal_bridge.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef SIGNALBRIDGE_H +#define SIGNALBRIDGE_H + +#include "constants.h" +#include "authcommon.h" + +#include + +#include + +class SignalBridge : public QObject, public Dtk::Core::DSingleton +{ + Q_OBJECT + friend class Dtk::Core::DSingleton; +private: + explicit SignalBridge(QObject *parent = nullptr) : QObject(parent) {} + +signals: + /** + * @brief 发送 extra info 给deepin-authentication + */ + void requestSendExtraInfo(const QString &account, const AuthCommon::AuthType authType, const QString &token); +}; + +#endif // SIGNALBRIDGE_H diff --git a/src/global_util/util_updateui.cpp b/src/global_util/util_updateui.cpp index 8f5f90f2..d3681b29 100644 --- a/src/global_util/util_updateui.cpp +++ b/src/global_util/util_updateui.cpp @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "util_updateui.h" diff --git a/src/global_util/util_updateui.h b/src/global_util/util_updateui.h index cf53e436..84a40174 100644 --- a/src/global_util/util_updateui.h +++ b/src/global_util/util_updateui.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include #include diff --git a/src/global_util/xkbparser.cpp b/src/global_util/xkbparser.cpp index facd4e22..2d101196 100644 --- a/src/global_util/xkbparser.cpp +++ b/src/global_util/xkbparser.cpp @@ -1,36 +1,15 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later -#include -#include +#include "xkbparser.h" +#include "constants.h" #include -#include #include -#include "xkbparser.h" +#include +#include XkbParser::XkbParser(QObject *parent) : QObject(parent) @@ -86,7 +65,7 @@ QString XkbParser::lookUpKeyboardKey(const QString &keyboard_value) for (int i = 0; i < KeyboardLayoutList.length(); i++) { if (KeyboardLayoutList[i].description == keyboard_value) { keyboard_key = QString("%1|").arg(KeyboardLayoutList[i].name); - qDebug() << "keyboard_key:" << keyboard_key; + qDebug() << "Look up keyboard key:" << keyboard_key; return keyboard_key; } else { for (int j = 0; j < KeyboardLayoutList[i].variantItemList.length(); j++) { @@ -109,14 +88,14 @@ bool XkbParser::parse() { if (baseFile.open(QIODevice::ReadOnly | QIODevice::Text)) { document.setContent(&baseFile); } else { - qDebug() << "Failed to open base.xml"; + qCWarning(DDE_SHELL) << "Failed to open base.xml"; return false; } QDomElement rootElement = document.documentElement(); if (rootElement.isNull()) { - qDebug() << "root element is null."; + qCWarning(DDE_SHELL) << "Root element is null."; return false; } @@ -125,7 +104,7 @@ bool XkbParser::parse() { QDomNodeList layoutNodes = layoutListElement.elementsByTagName("layout"); if (layoutNodes.isEmpty()) { - qDebug() << "layout list is empty."; + qCWarning(DDE_SHELL) << "Layout list is empty."; return false; } @@ -152,13 +131,13 @@ bool XkbParser::parse() { for (int variantIndex = 0; variantIndex < variantNodes.size(); ++variantIndex) { variantNode = variantNodes.at(variantIndex); if (variantNode.isNull()) { - qDebug() << "variant node is null."; + qCWarning(DDE_SHELL) << "Variant node is null"; continue; } QDomElement variantConfigElement = variantNode.firstChildElement("configItem"); if (variantConfigElement.isNull()) { - qDebug() << "variant config element is null."; + qCWarning(DDE_SHELL) << "Variant config element is null"; continue; } QDomElement variantNameElement = variantConfigElement.firstChildElement("name"); diff --git a/src/global_util/xkbparser.h b/src/global_util/xkbparser.h index 94188200..f08d2dc9 100644 --- a/src/global_util/xkbparser.h +++ b/src/global_util/xkbparser.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef XKBPARSER_H #define XKBPARSER_H diff --git a/src/libdde-auth/authcommon.h b/src/libdde-auth/authcommon.h index c0f2fd76..a4e5a47e 100644 --- a/src/libdde-auth/authcommon.h +++ b/src/libdde-auth/authcommon.h @@ -1,28 +1,20 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef AUTHCOMMON_H #define AUTHCOMMON_H +#include + +#define AUTH_TYPE_CAST(type) static_cast(type) +#define AUTH_FLAGS_CAST(flags) static_cast(flags) +#define AUTH_STATE_CAST(state) static_cast(state) + namespace AuthCommon { +Q_NAMESPACE; + /** * @brief The AuthFrameFlag enum * 认证框架是否可用的标志位 @@ -59,19 +51,23 @@ enum InputType { * 认证类型 */ enum AuthType { - AT_None = 0, // none - AT_Password = 1 << 0, // 密码 - AT_Fingerprint = 1 << 1, // 指纹 - AT_Face = 1 << 2, // 人脸 - AT_ActiveDirectory = 1 << 3, // AD域 - AT_Ukey = 1 << 4, // ukey - AT_FingerVein = 1 << 5, // 指静脉 - AT_Iris = 1 << 6, // 虹膜 - AT_PIN = 1 << 7, // PIN - AT_PAM = 1 << 29, // PAM - AT_Custom = 1 << 30, // 自定义 - AT_All = -1 // all + AT_None = 0, // none + AT_Password = 1 << 0, // 密码 + AT_Fingerprint = 1 << 1, // 指纹 + AT_Face = 1 << 2, // 人脸 + AT_ActiveDirectory = 1 << 3, // AD域 + AT_Ukey = 1 << 4, // ukey + AT_FingerVein = 1 << 5, // 指静脉 + AT_Iris = 1 << 6, // 虹膜 + AT_Passkey = 1 << 7, // Passkey + AT_Pattern = 1 << 8, // 手势 + AT_PAM = 1 << 29, // PAM + AT_Custom = 1 << 30, // 自定义 + AT_All = -1 // all }; +Q_DECLARE_FLAGS(AuthFlags, AuthType) +Q_FLAG_NS(AuthFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(AuthFlags) /** * @brief The AuthStatus enum @@ -91,8 +87,11 @@ enum AuthState { AS_Ended, // 认证已结束,调用 End 之后,每种成功关闭的都会发送此信号,当某种认证类型被锁定时,也会触发此信号 AS_Locked, // 认证已锁定,当认证类型锁定时,触发此信号。该信号不会给出锁定等待时间信息 AS_Recover, // 设备恢复,需要调用 Start 重新开启认证,对应 AS_Exception - AS_Unlocked // 认证解锁,对应 AS_Locked + AS_Unlocked, // 认证解锁,对应 AS_Locked + AS_Unknown, // 未知状态 + AS_VerifyCode, // 需要验证码 }; +Q_ENUM_NS(AuthState) } // namespace AuthCommon #endif // AUTHCOMMON_H diff --git a/src/libdde-auth/deepinauthframework.cpp b/src/libdde-auth/deepinauthframework.cpp index 2a253c51..f1e6959b 100644 --- a/src/libdde-auth/deepinauthframework.cpp +++ b/src/libdde-auth/deepinauthframework.cpp @@ -1,17 +1,16 @@ -#include "deepinauthframework.h" +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "deepinauthframework.h" +#include "encrypt_helper.h" #include "authcommon.h" #include "public_func.h" +#include "dbusconstant.h" #include -#include -#include - -#include -#include #include -#include #include #ifdef PAM_SUN_CODEBASE @@ -21,32 +20,58 @@ #endif #define PAM_SERVICE_SYSTEM_NAME "password-auth" -#define PAM_SERVICE_DEEPIN_NAME "common-auth" -#define PKCS1_HEADER "-----BEGIN RSA PUBLIC KEY-----" -#define PKCS8_HEADER "-----BEGIN PUBLIC KEY-----" -#define OPENSSLNAME "libssl.so" +#define PAM_SERVICE_DEEPIN_NAME "dde-lock" using namespace AuthCommon; DeepinAuthFramework::DeepinAuthFramework(QObject *parent) : QObject(parent) - , m_authenticateInter(new AuthInter(AUTHRNTICATESERVICE, "/com/deepin/daemon/Authenticate", QDBusConnection::systemBus(), this)) + , m_authenticateInter(new AuthInter(DSS_DBUS::authenticateService, DSS_DBUS::authenticatePath, QDBusConnection::systemBus(), this)) , m_PAMAuthThread(0) , m_authenticateControllers(new QMap()) , m_cancelAuth(false) , m_waitToken(true) - , m_encryptionHandle(nullptr) - , m_AES(new AES_KEY) - , m_BIO(nullptr) - , m_RSA(nullptr) + , m_isDAStartupCompleted(false) { connect(m_authenticateInter, &AuthInter::FrameworkStateChanged, this, &DeepinAuthFramework::FramworkStateChanged); connect(m_authenticateInter, &AuthInter::LimitUpdated, this, &DeepinAuthFramework::LimitsInfoChanged); connect(m_authenticateInter, &AuthInter::SupportedFlagsChanged, this, &DeepinAuthFramework::SupportedMixAuthFlagsChanged); connect(m_authenticateInter, &AuthInter::SupportEncryptsChanged, this, &DeepinAuthFramework::SupportedEncryptsChanged); + QDBusConnection::systemBus().connect(DSS_DBUS::authenticateService, DSS_DBUS::authenticatePath, DSS_DBUS::authenticateService, "DeviceChange", this, SLOT(onDeviceChanged(const int, const int))); + + if (m_authenticateInter->isValid()) { + m_isDAStartupCompleted = true; + } else{ + // 异步拉起DA,避免阻塞主线程 + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "StartServiceByName"); + message << DSS_DBUS::authenticateService << 0u; + QDBusPendingCall async = QDBusConnection::systemBus().asyncCall(message); + auto *watcher = new QDBusPendingCallWatcher(async); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher](QDBusPendingCallWatcher *callWatcher) { + QDBusPendingReply reply = *callWatcher; + if (!reply.isError()) { + m_isDAStartupCompleted = true; + Q_EMIT startupCompleted(); + } else { + qCWarning(DDE_SHELL) << "DA startup has error: " << reply.error().message(); + } + + callWatcher->deleteLater(); + watcher->deleteLater(); + }); + } + + connect(&m_authReminder, &QTimer::timeout, this, []{ + qCWarning(DDE_SHELL) << "No auth result recived after token send"; + }); + + m_authReminder.setSingleShot(false); +} - /* 暂时将加密方式固定,后续有修改再调整 */ - setEncryption(0, {1}); +void DeepinAuthFramework::onDeviceChanged(const int authType, const int state) +{ + qCInfo(DDE_SHELL) << "Device changed, auth type:" << authType << ", state:" << state; + Q_EMIT DeviceChanged(authType, state); } DeepinAuthFramework::~DeepinAuthFramework() @@ -55,9 +80,7 @@ DeepinAuthFramework::~DeepinAuthFramework() m_authenticateControllers->remove(key); } delete m_authenticateControllers; - delete m_AES; - - DestoryAuthenticate(); + DestroyAuthenticate(); } /** @@ -70,15 +93,15 @@ void DeepinAuthFramework::CreateAuthenticate(const QString &account) if (account == m_account && m_PAMAuthThread != 0) { return; } - qInfo() << "Create PAM authenticate thread:" << account << m_PAMAuthThread; + qCInfo(DDE_SHELL) << "Create PAM authenticate thread, accout: " << account << "PAM auth thread: " << m_PAMAuthThread; m_account = account; - DestoryAuthenticate(); + DestroyAuthenticate(); m_cancelAuth = false; m_waitToken = true; int rc = pthread_create(&m_PAMAuthThread, nullptr, &PAMAuthWorker, this); if (rc != 0) { - qCritical() << "failed to create the authentication thread: %s" << strerror(errno); + qCritical() << "ERROR: failed to create the authentication thread: %s" << strerror(errno); } } @@ -94,7 +117,7 @@ void *DeepinAuthFramework::PAMAuthWorker(void *arg) if (authFramework != nullptr) { authFramework->PAMAuthentication(authFramework->m_account); } else { - qCritical() << "pam auth worker deepin framework is nullptr"; + qCritical() << "ERROR: pam auth worker deepin framework is nullptr"; } return nullptr; } @@ -112,24 +135,30 @@ void DeepinAuthFramework::PAMAuthentication(const QString &account) int ret = pam_start(serviceName, account.toLocal8Bit().data(), &conv, &m_pamHandle); if (ret != PAM_SUCCESS) { - qCritical() << "PAM start failed:" << pam_strerror(m_pamHandle, ret) << ret; + qCritical() << "ERROR: PAM start failed, error: " << pam_strerror(m_pamHandle, ret) << ", start infomation: " << ret; } else { - qDebug() << "PAM start..."; + qCDebug(DDE_SHELL) << "PAM start..."; } int rc = pam_authenticate(m_pamHandle, 0); if (rc != PAM_SUCCESS) { - qWarning() << "PAM authenticate failed:" << pam_strerror(m_pamHandle, rc) << rc; - if (m_message.isEmpty()) m_message = pam_strerror(m_pamHandle, rc); + qCWarning(DDE_SHELL) << "PAM authenticate failed, error: " << pam_strerror(m_pamHandle, rc) << ", PAM authenticate: " << rc; + if (m_message.isEmpty()){ + if(rc == PAM_AUTH_ERR){ + m_message = tr("Wrong Password"); + }else{ + m_message = pam_strerror(m_pamHandle, rc); + } + } } else { - qDebug() << "PAM authenticate finished."; + qCDebug(DDE_SHELL) << "PAM authenticate finished."; } int re = pam_end(m_pamHandle, rc); if (re != PAM_SUCCESS) { - qCritical() << "PAM end failed:" << pam_strerror(m_pamHandle, re) << re; + qCritical() << "PAM end failed:" << pam_strerror(m_pamHandle, re) << "PAM end infomation: " << re; } else { - qDebug() << "PAM end..."; + qCDebug(DDE_SHELL) << "PAM end..."; } if (rc == 0) { @@ -159,17 +188,17 @@ int DeepinAuthFramework::PAMConversation(int num_msg, const pam_message **msg, p QPointer isThreadAlive(app_ptr); if (!isThreadAlive) { - qWarning() << "pam: application is null"; + qCWarning(DDE_SHELL) << "PAM conversation: application is null"; return PAM_CONV_ERR; } if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) { - qWarning() << "PAM_CONV_ERR :" << num_msg; + qCWarning(DDE_SHELL) << "PAM conversation: message num error :" << num_msg; return PAM_CONV_ERR; } if ((aresp = static_cast(calloc(static_cast(num_msg), sizeof(*aresp)))) == nullptr) { - qWarning() << "PAM_BUF_ERR"; + qCWarning(DDE_SHELL) << "PAM conversation buffer error: " << aresp; return PAM_BUF_ERR; } const QString message = QString::fromLocal8Bit(PAM_MSG_MEMBER(msg, idx, msg)); @@ -177,11 +206,11 @@ int DeepinAuthFramework::PAMConversation(int num_msg, const pam_message **msg, p switch (PAM_MSG_MEMBER(msg, idx, msg_style)) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: { - qDebug() << "pam auth echo:" << message; + qCDebug(DDE_SHELL) << "PAM auth echo:" << message; app_ptr->UpdateAuthState(AS_Prompt, message); /* 等待用户输入密码 */ while (app_ptr->m_waitToken) { - qDebug() << "Waiting for the password..."; + qCDebug(DDE_SHELL) << "Waiting for the password..."; if (app_ptr->m_cancelAuth) { app_ptr->m_cancelAuth = false; return PAM_ABORT; @@ -191,7 +220,7 @@ int DeepinAuthFramework::PAMConversation(int num_msg, const pam_message **msg, p app_ptr->m_waitToken = true; if (!QPointer(app_ptr)) { - qCritical() << "pam: deepin auth framework is null"; + qCritical() << "ERROR: PAM deepin auth framework is null"; return PAM_CONV_ERR; } @@ -205,14 +234,14 @@ int DeepinAuthFramework::PAMConversation(int num_msg, const pam_message **msg, p break; } case PAM_ERROR_MSG: { - qDebug() << "pam auth error: " << message; + qCDebug(DDE_SHELL) << "PAM auth error: " << message; app_ptr->m_message = message; app_ptr->UpdateAuthState(AS_Failure, message); aresp[idx].resp_retcode = PAM_SUCCESS; break; } case PAM_TEXT_INFO: { - qDebug() << "pam auth info: " << message; + qCDebug(DDE_SHELL) << "PAM auth info: " << message; app_ptr->m_message = message; app_ptr->UpdateAuthState(AS_Prompt, message); aresp[idx].resp_retcode = PAM_SUCCESS; @@ -245,7 +274,7 @@ void DeepinAuthFramework::SendToken(const QString &token) if (!m_waitToken) { return; } - qInfo() << "Send token to PAM"; + qCInfo(DDE_SHELL) << "Token arrived, is it empty ? " << token.isEmpty(); m_token = token; m_waitToken = false; } @@ -256,7 +285,7 @@ void DeepinAuthFramework::SendToken(const QString &token) * @param state * @param message */ -void DeepinAuthFramework::UpdateAuthState(const int state, const QString &message) +void DeepinAuthFramework::UpdateAuthState(const AuthState state, const QString &message) { emit AuthStateChanged(AT_PAM, state, message); } @@ -264,78 +293,21 @@ void DeepinAuthFramework::UpdateAuthState(const int state, const QString &messag /** * @brief 结束 PAM 认证服务 */ -void DeepinAuthFramework::DestoryAuthenticate() +void DeepinAuthFramework::DestroyAuthenticate() { if (m_PAMAuthThread == 0) { return; } - qInfo() << "Destory PAM authenticate thread"; + qCInfo(DDE_SHELL) << "Destroy PAM authenticate thread"; m_cancelAuth = true; pthread_cancel(m_PAMAuthThread); pthread_join(m_PAMAuthThread, nullptr); m_PAMAuthThread = 0; } -/** - * @brief 设置加密类型和加密方式 - * - * @param type - * @param method - */ -void DeepinAuthFramework::setEncryption(const int type, ArrayInt method) -{ - m_encryptType = type; - m_encryptMethod = method; -} - -/** - * @brief 初始化加密服务 - */ -void DeepinAuthFramework::initEncryptionService() -{ - if ((m_encryptionHandle = dlopen(OPENSSLNAME, RTLD_NOW)) == nullptr) { - qCritical() << "Failed to load" << OPENSSLNAME; - return; - } - m_F_AES_cbc_encrypt = reinterpret_cast(dlsym(m_encryptionHandle, "AES_cbc_encrypt")); - m_F_AES_set_encrypt_key = reinterpret_cast(dlsym(m_encryptionHandle, "AES_set_encrypt_key")); - m_F_BIO_new = reinterpret_cast(dlsym(m_encryptionHandle, "BIO_new")); - m_F_BIO_puts = reinterpret_cast(dlsym(m_encryptionHandle, "BIO_puts")); - m_F_BIO_s_mem = reinterpret_cast(dlsym(m_encryptionHandle, "BIO_s_mem")); - m_F_PEM_read_bio_RSAPublicKey = reinterpret_cast(dlsym(m_encryptionHandle, "PEM_read_bio_RSAPublicKey")); - m_F_PEM_read_bio_RSA_PUBKEY = reinterpret_cast(dlsym(m_encryptionHandle, "PEM_read_bio_RSA_PUBKEY")); - m_F_RSA_public_encrypt = reinterpret_cast(dlsym(m_encryptionHandle, "RSA_public_encrypt")); - m_F_RSA_size = reinterpret_cast(dlsym(m_encryptionHandle, "RSA_size")); - m_F_RSA_free = reinterpret_cast(dlsym(m_encryptionHandle, "RSA_free")); - m_F_BIO_free = reinterpret_cast(dlsym(m_encryptionHandle, "BIO_free")); - - m_BIO = m_F_BIO_new(m_F_BIO_s_mem()); - m_F_BIO_puts(m_BIO, m_publicKey.toLatin1().data()); - - if (strncmp(m_publicKey.toLatin1().data(), PKCS8_HEADER, strlen(PKCS8_HEADER)) == 0) { - m_RSA = m_F_PEM_read_bio_RSA_PUBKEY(m_BIO, nullptr, nullptr, nullptr); - } else if (strncmp(m_publicKey.toLatin1().data(), PKCS1_HEADER, strlen(PKCS1_HEADER)) == 0) { - m_RSA = m_F_PEM_read_bio_RSAPublicKey(m_BIO, nullptr, nullptr, nullptr); - } - - /* 生成对称加密的密钥 */ - srand(static_cast(time(nullptr))); - int randNum = (10000000 + rand() % 10000000) % 100000000; - m_symmetricKey = QString::number(randNum) + QString::number(randNum); -} - -/** - * @brief 加密对称加密的密钥并发送给认证服务 - * - * @param account - */ -void DeepinAuthFramework::encryptSymmtricKey(const QString &account) +bool DeepinAuthFramework::IsUsingPamAuth() { - int size = m_F_RSA_size(m_RSA); - char *ciphertext = new char[static_cast(size)]; - m_F_RSA_public_encrypt(m_symmetricKey.length(), reinterpret_cast(m_symmetricKey.toLatin1().data()), reinterpret_cast(ciphertext), m_RSA, 1); - m_authenticateControllers->value(account)->SetSymmetricKey(QByteArray(ciphertext, size)); - delete[] ciphertext; + return m_PAMAuthThread != 0; } /** @@ -345,14 +317,17 @@ void DeepinAuthFramework::encryptSymmtricKey(const QString &account) * @param authType 认证方式(多因、单因,一种或多种) * @param encryptType 加密方式 */ -void DeepinAuthFramework::CreateAuthController(const QString &account, const int authType, const int appType) +void DeepinAuthFramework::CreateAuthController(const QString &account, const AuthFlags authType, const int appType) { if (m_authenticateControllers->contains(account) && m_authenticateControllers->value(account)->isValid()) { return; } const QString authControllerInterPath = m_authenticateInter->Authenticate(account, authType, appType); - qInfo() << "Create Authenticate Session:" << account << authType << appType << authControllerInterPath; - AuthControllerInter *authControllerInter = new AuthControllerInter("com.deepin.daemon.Authenticate", authControllerInterPath, QDBusConnection::systemBus(), this); + qCInfo(DDE_SHELL) << "Create auth controller, account:" << account + << ", Auth type:"<< authType + << ", App type:" << appType + << ", Authentication session path: " << authControllerInterPath; + AuthControllerInter *authControllerInter = new AuthControllerInter(DSS_DBUS::authenticateService, authControllerInterPath, QDBusConnection::systemBus(), this); m_authenticateControllers->insert(account, authControllerInter); connect(authControllerInter, &AuthControllerInter::FactorsInfoChanged, this, &DeepinAuthFramework::FactorsInfoChanged); @@ -361,37 +336,51 @@ void DeepinAuthFramework::CreateAuthController(const QString &account, const int connect(authControllerInter, &AuthControllerInter::PINLenChanged, this, &DeepinAuthFramework::PINLenChanged); connect(authControllerInter, &AuthControllerInter::PromptChanged, this, &DeepinAuthFramework::PromptChanged); connect(authControllerInter, &AuthControllerInter::Status, this, [this](int flag, int state, const QString &msg) { - emit AuthStateChanged(flag, state, msg); + if (m_authReminder.isActive()) { + m_authReminder.stop(); + qCWarning(DDE_SHELL) << "reminder stopped for status changed"; + } + + const AuthType type = AUTH_TYPE_CAST(flag); + const AuthState authState = AUTH_STATE_CAST(state); + emit AuthStateChanged(type, authState, msg); // 当人脸或者虹膜认证成功 或者 指纹识别失败/成功 时唤醒屏幕 - if (((AT_Face == flag || AT_Iris == flag) && AS_Success == state) - || (AT_Fingerprint == flag && (AS_Failure == state || AS_Success == state))) { + if (((AT_Face == type || AT_Iris == type) && AS_Success == authState) + || (AT_Fingerprint == type && (AS_Failure == authState || AS_Success == authState)) + || (AT_Passkey == type && (AS_Failure == authState || AS_Success == authState))) { system("xset dpms force on"); } }); + emit SessionCreated(); emit MFAFlagChanged(authControllerInter->isMFA()); emit FactorsInfoChanged(authControllerInter->factorsInfo()); emit FuzzyMFAChanged(authControllerInter->isFuzzyMFA()); emit PINLenChanged(authControllerInter->pINLen()); emit PromptChanged(authControllerInter->prompt()); - int encryptType; - ArrayInt encryptMethod; - QDBusReply reply = authControllerInter->EncryptKey(m_encryptType, m_encryptMethod, encryptMethod, m_publicKey); - encryptType = reply.value(); - if (encryptType != m_encryptType || encryptMethod != m_encryptMethod) { - qWarning() << "The current encryption method is not supported, use the default encryption method."; - m_encryptType = encryptType; - m_encryptMethod = encryptMethod; - } - if (m_publicKey.isEmpty()) { - qCritical() << "Failed to get the public key!"; + + int DAEncryptType; + ArrayInt DAEncryptMethod; + QString publicKey; + // 获取非对称加密公钥 + QDBusReply reply = authControllerInter->EncryptKey( + EncryptHelper::ref().encryptType(), + EncryptHelper::ref().encryptMethod(), + DAEncryptMethod, + publicKey); + DAEncryptType = reply.value(); + + // 使用DA返回的加密算法; 例如,如果是没有适配SM2算法的DA,那么就使用RSA + EncryptHelper::ref().setEncryption(DAEncryptType, DAEncryptMethod); + if (publicKey.isEmpty()) { + qCritical() << "ERROR: Failed to get the public key!"; return; } - - initEncryptionService(); - encryptSymmtricKey(account); + EncryptHelper::ref().setPublicKey(publicKey); + EncryptHelper::ref().initEncryptionService(); + m_authenticateControllers->value(account)->SetSymmetricKey(EncryptHelper::ref().encryptSymmetricalKey()); } /** @@ -399,23 +388,18 @@ void DeepinAuthFramework::CreateAuthController(const QString &account, const int * * @param account 用户名 */ -void DeepinAuthFramework::DestoryAuthController(const QString &account) +void DeepinAuthFramework::DestroyAuthController(const QString &account) { if (!m_authenticateControllers->contains(account)) { return; } AuthControllerInter *authControllerInter = m_authenticateControllers->value(account); - qInfo() << "Destory Authenticate Sesssion:" << account << authControllerInter->path(); + qCInfo(DDE_SHELL) << "Destroy authenticate session:" << account << ", interface path: " << authControllerInter->path(); authControllerInter->End(AT_All); authControllerInter->Quit(); m_authenticateControllers->remove(account); delete authControllerInter; - - if (m_encryptionHandle) { - m_F_RSA_free(m_RSA); - m_F_BIO_free(m_BIO); - dlclose(m_encryptionHandle); - } + EncryptHelper::ref().releaseResources(); } /** @@ -425,13 +409,16 @@ void DeepinAuthFramework::DestoryAuthController(const QString &account) * @param authType 认证类型(可传入一种或多种) * @param timeout 设定超时时间(默认 -1) */ -void DeepinAuthFramework::StartAuthentication(const QString &account, const int authType, const int timeout) +void DeepinAuthFramework::StartAuthentication(const QString &account, const AuthFlags authType, const int timeout) { if (!m_authenticateControllers->contains(account)) { return; } + int ret = m_authenticateControllers->value(account)->Start(authType, timeout); - qInfo() << "Start Authenticate Session:" << account << authType << ret; + qCInfo(DDE_SHELL) << "Start authentication, account:" << account << ", auth type" << authType << ", ret:" << ret; + + m_lastAuthUser = account; } /** @@ -440,12 +427,12 @@ void DeepinAuthFramework::StartAuthentication(const QString &account, const int * @param account 账户 * @param authType 认证类型 */ -void DeepinAuthFramework::EndAuthentication(const QString &account, const int authType) +void DeepinAuthFramework::EndAuthentication(const QString &account, const AuthFlags authType) { if (!m_authenticateControllers->contains(account)) { return; } - qInfo() << "End Authentication:" << account << authType; + qCInfo(DDE_SHELL) << "End authentication:" << ", account: " << account << "auth type: " << authType; m_authenticateControllers->value(account)->End(authType).waitForFinished(); } @@ -456,36 +443,17 @@ void DeepinAuthFramework::EndAuthentication(const QString &account, const int au * @param authType 认证类型 * @param token 密文 */ -void DeepinAuthFramework::SendTokenToAuth(const QString &account, const int authType, const QString &token) +void DeepinAuthFramework::SendTokenToAuth(const QString &account, const AuthType authType, const QString &token) { + qCInfo(DDE_SHELL) << "Send token to auth, account: " << account << ", auth type:" << authType; if (!m_authenticateControllers->contains(account)) { + qCWarning(DDE_SHELL) << "account not included"; return; } - qInfo() << "Send token to authentication:" << account << authType; - - const int tokenSize = token.size(); - const int padding = AES_BLOCK_SIZE - tokenSize % AES_BLOCK_SIZE; - const int blockCount = token.length() / AES_BLOCK_SIZE + 1; - const int bufferSize = blockCount * AES_BLOCK_SIZE; - char *tokenBuffer = new char[static_cast(bufferSize)]; - memset(tokenBuffer, padding, static_cast(bufferSize)); - memcpy(tokenBuffer, token.toLatin1().data(), static_cast(tokenSize)); - char *ciphertext = new char[static_cast(bufferSize)]; - memset(ciphertext, 0, static_cast(bufferSize)); - int ret = m_F_AES_set_encrypt_key(reinterpret_cast(m_symmetricKey.toLatin1().data()), m_symmetricKey.length() * 8, m_AES); - if (ret < 0) { - qCritical() << "Failed to set symmetric key!"; - delete[] tokenBuffer; - delete[] ciphertext; - return; - } - unsigned char *iv = new unsigned char[AES_BLOCK_SIZE]; - memset(iv, 0, AES_BLOCK_SIZE); - m_F_AES_cbc_encrypt(reinterpret_cast(tokenBuffer), reinterpret_cast(ciphertext), static_cast(bufferSize), m_AES, iv, AES_ENCRYPT); - m_authenticateControllers->value(account)->SetToken(authType, QByteArray(ciphertext, bufferSize)); - delete[] tokenBuffer; - delete[] ciphertext; - delete[] iv; + + QByteArray ba = EncryptHelper::ref().getEncryptedToken(token); + m_authenticateControllers->value(account)->SetToken(authType, ba); + m_authReminder.start(3000); } /** @@ -507,9 +475,9 @@ void DeepinAuthFramework::SetAuthQuitFlag(const QString &account, const int flag * * @return int */ -int DeepinAuthFramework::GetSupportedMixAuthFlags() const +AuthFlags DeepinAuthFramework::GetSupportedMixAuthFlags() const { - return m_authenticateInter->supportedFlags(); + return AUTH_FLAGS_CAST(m_authenticateInter->supportedFlags()); } /** @@ -622,7 +590,13 @@ bool DeepinAuthFramework::SetPrivilegesEnable(const QString &account, const QStr if (!m_authenticateControllers->contains(account)) { return false; } - return m_authenticateControllers->value(account)->PrivilegesEnable(path); + + QDBusPendingReply reply = m_authenticateControllers->value(account)->PrivilegesEnable(path); + reply.waitForFinished(); + if(reply.isError()) { + return false; + } + return reply.value(); } /** @@ -678,9 +652,22 @@ bool DeepinAuthFramework::authSessionExist(const QString &account) const */ bool DeepinAuthFramework::isDeepinAuthValid() const { - qDebug() << Q_FUNC_INFO - << ", frameworkState" << m_authenticateInter->frameworkState() - << ", isServiceRegistered: " << QDBusConnection::systemBus().interface()->isServiceRegistered(AUTHRNTICATESERVICE); - return QDBusConnection::systemBus().interface()->isServiceRegistered(AUTHRNTICATESERVICE) - && Available == GetFrameworkState(); + return QDBusConnection::systemBus().interface()->isServiceRegistered(DSS_DBUS::authenticateService) + && (Available == GetFrameworkState()); +} + +void DeepinAuthFramework::sendExtraInfo(const QString &account, AuthType authType, const QString &info) +{ + if (!m_authenticateControllers->contains(account)) { + qCWarning(DDE_SHELL) << "Do not contain account"; + return; + } + qInfo() << "Send extra info to authentication:" << account << authType; + AuthControllerInter *inter = m_authenticateControllers->value(account); + QDBusMessage msg = QDBusMessage::createMethodCall(inter->service(), inter->path(), inter->interface(), "SetExtraInfo"); + msg << authType << QString("{\"type\":%1,\"data\":\"%2\"}").arg(authType).arg(info); + QDBusPendingCall reply = inter->connection().asyncCall(msg, 2000); + if (reply.isError()) { + qCWarning(DDE_SHELL) << "Send extra info error:" << reply.error(); + } } diff --git a/src/libdde-auth/deepinauthframework.h b/src/libdde-auth/deepinauthframework.h index 9a547d73..31455998 100644 --- a/src/libdde-auth/deepinauthframework.h +++ b/src/libdde-auth/deepinauthframework.h @@ -1,30 +1,27 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef DEEPINAUTHFRAMEWORK_H #define DEEPINAUTHFRAMEWORK_H +#include "authcommon.h" + #include -#include +#ifndef ENABLE_DSS_SNIPE #include #include -#include -#include - -#define AUTHRNTICATESERVICE "com.deepin.daemon.Authenticate" -#define AUTHRNTICATEINTERFACE "com.deepin.daemon.Authenticate.Session" using AuthInter = com::deepin::daemon::Authenticate; using AuthControllerInter = com::deepin::daemon::authenticate::Session; +#else +#include "authenticate1interface.h" +#include "session2interface.h" -using FUNC_AES_CBC_ENCRYPT = void (*)(const unsigned char *in, unsigned char *out, size_t length, const void *aes, unsigned char *ivec, const int enc); -using FUNC_AES_SET_ENCRYPT_KEY = int (*)(const unsigned char *userKey, const int bits, void *aes); -using FUNC_BIO_S_MEM = void *(*)(); -using FUNC_BIO_NEW = void *(*)(void *); -using FUNC_BIO_PUTS = int (*)(void *, const char *); -using FUNC_PEM_READ_BIO_RSA_PUBKEY = void *(*)(void *, void *, void *, void *); -using FUNC_PEM_READ_BIO_RSAPUBLICKEY = void *(*)(void *, void *, void *, void *); -using FUNC_RSA_PUBLIC_ENCRYPT = void *(*)(int flen, const unsigned char *from, unsigned char *to, void *rsa, int padding); -using FUNC_RSA_SIZE = int (*)(void *); -using FUNC_RSA_FREE = void (*)(void *); +using AuthInter = org::deepin::dde::Authenticate1; +using AuthControllerInter = org::deepin::dde::authenticate1::Session; +#endif class DeepinAuthFramework : public QObject { @@ -43,11 +40,13 @@ class DeepinAuthFramework : public QObject /* Compatible with old authentication methods */ void CreateAuthenticate(const QString &account); void SendToken(const QString &token); - void DestoryAuthenticate(); + void DestroyAuthenticate(); + // 是否正在使用pam认证 + bool IsUsingPamAuth(); /* com.deepin.daemon.Authenticate */ int GetFrameworkState() const; - int GetSupportedMixAuthFlags() const; + AuthCommon::AuthFlags GetSupportedMixAuthFlags() const; QString GetPreOneKeyLogin(const int flag) const; QString GetLimitedInfo(const QString &account) const; QString GetSupportedEncrypts() const; @@ -64,8 +63,11 @@ class DeepinAuthFramework : public QObject void setEncryption(const int type, const ArrayInt method); bool authSessionExist(const QString &account) const; bool isDeepinAuthValid() const; + bool isDAStartupCompleted() const { return m_isDAStartupCompleted;} + void sendExtraInfo(const QString &account, AuthCommon::AuthType authType, const QString &info); signals: + void startupCompleted(); /* com.deepin.daemon.Authenticate */ void LimitsInfoChanged(const QString &); void SupportedMixAuthFlagsChanged(const int); @@ -78,25 +80,26 @@ class DeepinAuthFramework : public QObject void FactorsInfoChanged(const MFAInfoList &); void PINLenChanged(const int); void AuthStateChanged(const int, const int, const QString &); + void SessionCreated(); + void DeviceChanged(const int, const int); + void TokenAccountMismatch(const QString &); public slots: /* New authentication framework */ - void CreateAuthController(const QString &account, const int authType, const int appType); - void DestoryAuthController(const QString &account); - void StartAuthentication(const QString &account, const int authType, const int timeout); - void EndAuthentication(const QString &account, const int authType); - void SendTokenToAuth(const QString &account, const int authType, const QString &token); + void CreateAuthController(const QString &account, const AuthCommon::AuthFlags authType, const int appType); + void DestroyAuthController(const QString &account); + void StartAuthentication(const QString &account, const AuthCommon::AuthFlags authType, const int timeout); + void EndAuthentication(const QString &account, const AuthCommon::AuthFlags authType); + void SendTokenToAuth(const QString &account, const AuthCommon::AuthType authType, const QString &token); void SetAuthQuitFlag(const QString &account, const int flag = AutoQuit); + void onDeviceChanged(const int authType, const int state); private: /* Compatible with old authentication methods */ static void *PAMAuthWorker(void *arg); void PAMAuthentication(const QString &account); static int PAMConversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *app_data); - void UpdateAuthState(const int state, const QString &message); - - void initEncryptionService(); - void encryptSymmtricKey(const QString &account); + void UpdateAuthState(const AuthCommon::AuthState state, const QString &message); private: AuthInter *m_authenticateInter; @@ -111,22 +114,10 @@ public slots: QMap *m_authenticateControllers; bool m_cancelAuth; bool m_waitToken; + bool m_isDAStartupCompleted; - void *m_encryptionHandle; - FUNC_AES_CBC_ENCRYPT m_F_AES_cbc_encrypt; - FUNC_AES_SET_ENCRYPT_KEY m_F_AES_set_encrypt_key; - FUNC_BIO_NEW m_F_BIO_new; - FUNC_BIO_PUTS m_F_BIO_puts; - FUNC_BIO_S_MEM m_F_BIO_s_mem; - FUNC_PEM_READ_BIO_RSAPUBLICKEY m_F_PEM_read_bio_RSAPublicKey; - FUNC_PEM_READ_BIO_RSA_PUBKEY m_F_PEM_read_bio_RSA_PUBKEY; - FUNC_RSA_FREE m_F_RSA_free; - FUNC_RSA_FREE m_F_BIO_free; - FUNC_RSA_PUBLIC_ENCRYPT m_F_RSA_public_encrypt; - FUNC_RSA_SIZE m_F_RSA_size; - AES_KEY *m_AES; - void *m_BIO; - void *m_RSA; + QTimer m_authReminder; + QString m_lastAuthUser; }; #endif // DEEPINAUTHFRAMEWORK_H diff --git a/src/libdde-auth/encrypt_helper.cpp b/src/libdde-auth/encrypt_helper.cpp new file mode 100644 index 00000000..3c5b1f67 --- /dev/null +++ b/src/libdde-auth/encrypt_helper.cpp @@ -0,0 +1,212 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "encrypt_helper.h" +#include "public_func.h" + +#include + +#define PKCS1_HEADER "-----BEGIN RSA PUBLIC KEY-----" +#define PKCS8_HEADER "-----BEGIN PUBLIC KEY-----" + +EncryptHelper::EncryptHelper() + : m_BIO(nullptr) + , m_RSA(nullptr) + , m_ecKey(nullptr) +#ifndef PREFER_USING_GM + , m_encryptType(ET_RSA) +#else + , m_encryptType(ET_SM2) +#endif + , m_encryptMethod({1}) +{ + +} + +EncryptHelper::~EncryptHelper() +{ + releaseResources(); +} + +/** + * @brief 初始化加密服务,创建对称加密密钥 + */ +void EncryptHelper::initEncryptionService() +{ + m_BIO = BIO_new(BIO_s_mem()); + BIO_puts(m_BIO, m_publicKey.toLatin1().data()); + + if (ET_SM2 == m_encryptType) { + PEM_read_bio_EC_PUBKEY(m_BIO, &m_ecKey, nullptr, nullptr); + } else { + if (strncmp(m_publicKey.toLatin1().data(), PKCS8_HEADER, strlen(PKCS8_HEADER)) == 0) { + PEM_read_bio_RSA_PUBKEY(m_BIO, &m_RSA, nullptr, nullptr); + } else if (strncmp(m_publicKey.toLatin1().data(), PKCS1_HEADER, strlen(PKCS1_HEADER)) == 0) { + PEM_read_bio_RSAPublicKey(m_BIO, &m_RSA, nullptr, nullptr); + } + } + + /* 生成对称加密的密钥 */ + srand(static_cast(time(nullptr))); + int randNum = (10000000 + rand() % 10000000) % 100000000; + m_symmetricKey = QString::number(randNum) + QString::number(randNum); +} + +/** + * @brief 设置加密类型和加密方式 + * + * @param type 非对称加密类型 + * @param method 默认传{1},没人知道为什么 + */ +void EncryptHelper::setEncryption(const int type, ArrayInt method) +{ + qCInfo(DDE_SHELL) << "Set encryption type: " << type; + m_encryptType = type; + m_encryptMethod = method; +} + +/** + * @brief 用非对称加密公钥加密对称加密的密钥 + * + * @return 加密后的对称加密密钥 + */ +QByteArray EncryptHelper::encryptSymmetricalKey() +{ + if (ET_SM2 == m_encryptType) { +#ifdef PREFER_USING_GM + return SM2EncryptSymmetricalKey(); +#endif + } + + return RSAEncryptSymmetricalKey(); +} + + +QByteArray EncryptHelper::RSAEncryptSymmetricalKey() +{ + int size = RSA_size(m_RSA); + char *ciphertext = new char[static_cast(size)]; + RSA_public_encrypt(m_symmetricKey.length(), reinterpret_cast(m_symmetricKey.toLatin1().data()), reinterpret_cast(ciphertext), m_RSA, 1); + QByteArray ba = QByteArray(ciphertext, size); + delete[] ciphertext; + return ba; +} + + +#ifdef PREFER_USING_GM +QByteArray EncryptHelper::SM2EncryptSymmetricalKey() +{ + size_t csize = 0; + size_t psize = m_symmetricKey.length(); + if (1 != sm2_ciphertext_size(m_ecKey, EVP_sm3(), psize, &csize)) { + qCritical() << "ERROR: Can't get sm2 ciphertext size"; + return ""; + } + + uint8_t *cipherText = new uint8_t[csize]; + if (1 != sm2_encrypt(m_ecKey, EVP_sm3(), (uint8_t *)m_symmetricKey.toStdString().c_str(), psize, cipherText, &csize)) { + qCritical() << "ERROR:Can't encrypt sm2 cipher"; + delete[] cipherText; + return ""; + } + + QByteArray ba(reinterpret_cast(cipherText), csize); + delete[] cipherText; + return ba; +} +#endif + +QByteArray EncryptHelper::getEncryptedToken(const QString &token) +{ + const int tokenSize = token.size(); + const int padding = AES_BLOCK_SIZE - tokenSize % AES_BLOCK_SIZE; + const int blockCount = token.length() / AES_BLOCK_SIZE + 1; + const int bufferSize = blockCount * AES_BLOCK_SIZE; + char *tokenBuffer = nullptr; + char *ciphertext = nullptr; + unsigned char *iv = nullptr; + EVP_CIPHER_CTX *ctx = nullptr; + QByteArray ba; + + tokenBuffer = new char[static_cast(bufferSize)]; + memset(tokenBuffer, padding, static_cast(bufferSize)); + memcpy(tokenBuffer, token.toLatin1().data(), static_cast(tokenSize)); + ciphertext = new char[static_cast(bufferSize)]; + memset(ciphertext, 0, static_cast(bufferSize)); + + AES_KEY aes; + int ret = 0; + do { + if (ET_SM2 == m_encryptType) { +#ifdef PREFER_USING_GM + qCInfo(DDE_SHELL) << "PREFER_USING_GM"; + ctx = EVP_CIPHER_CTX_new(); + if (ctx == nullptr) { + break; + } + ret = EVP_CipherInit(ctx, EVP_sm4_ecb(), reinterpret_cast(m_symmetricKey.toLatin1().data()), nullptr, 1); + if (ret != 1) { + break; + } +#endif + } else { + AES_set_encrypt_key(reinterpret_cast(m_symmetricKey.toLatin1().data()), m_symmetricKey.length() * 8, &aes); + } + if (ret < 0) { + qCritical() << "Failed to set symmetric key!"; + break; + } + iv = new unsigned char[AES_BLOCK_SIZE]; + memset(iv, 0, AES_BLOCK_SIZE); + if (ET_SM2 == m_encryptType) { +#ifdef PREFER_USING_GM + ret = EVP_Cipher(ctx, reinterpret_cast(ciphertext),reinterpret_cast(tokenBuffer), static_cast(bufferSize)); + if (1 != ret) { + break; + } + +#endif + } else { + AES_cbc_encrypt(reinterpret_cast(tokenBuffer), reinterpret_cast(ciphertext), static_cast(bufferSize), &aes, iv, AES_ENCRYPT); + } + + ba = QByteArray(ciphertext, bufferSize); + } while (0); + + if(ctx){ + EVP_CIPHER_CTX_free(ctx); + } + + if(ciphertext){ + delete[] ciphertext; + } + + if(tokenBuffer){ + delete[] tokenBuffer; + } + + if(iv){ + delete[] iv; + } + + return ba; +} + +void EncryptHelper::releaseResources() +{ + if (m_BIO) { + BIO_free(m_BIO); + m_BIO = nullptr; + } + + if (m_RSA) { + RSA_free(m_RSA); + m_RSA = nullptr; + } + + if (m_ecKey) { + EC_KEY_free(m_ecKey); + m_ecKey = nullptr; + } +} diff --git a/src/libdde-auth/encrypt_helper.h b/src/libdde-auth/encrypt_helper.h new file mode 100644 index 00000000..5cbbcb06 --- /dev/null +++ b/src/libdde-auth/encrypt_helper.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include + +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif +#ifdef PREFER_USING_GM +#include +#endif +#ifdef __cplusplus +} +#endif +#include + +#include + +class EncryptHelper : public Dtk::Core::DSingleton +{ + friend class Dtk::Core::DSingleton; + +public: + enum EncryptType { + ET_RSA = 0, + ET_SM2 + }; + + void setEncryption(const int type, ArrayInt method = {1}); + QByteArray encryptSymmetricalKey(); + QByteArray getEncryptedToken(const QString &token); + int encryptType() const { return m_encryptType; } + ArrayInt encryptMethod() const { return m_encryptMethod; } + void setPublicKey(const QString &publicKey) { m_publicKey = publicKey; } + void initEncryptionService(); + void releaseResources(); + +private: + EncryptHelper(); + ~EncryptHelper(); + + QByteArray RSAEncryptSymmetricalKey(); +#ifdef PREFER_USING_GM + QByteArray SM2EncryptSymmetricalKey(); +#endif + +private: + BIO *m_BIO; + RSA *m_RSA; + EC_KEY *m_ecKey; + int m_encryptType; + QString m_symmetricKey; + QString m_publicKey; + ArrayInt m_encryptMethod; +}; diff --git a/src/lightdm-deepin-greeter/greeterworker.cpp b/src/lightdm-deepin-greeter/greeterworker.cpp index 163fcdca..6f591079 100644 --- a/src/lightdm-deepin-greeter/greeterworker.cpp +++ b/src/lightdm-deepin-greeter/greeterworker.cpp @@ -1,22 +1,39 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "greeterworker.h" #include "authcommon.h" #include "keyboardmonitor.h" #include "userinfo.h" +#include "dconfig_helper.h" +#include "login_plugin_util.h" +#include "mfasequencecontrol.h" +#include "signal_bridge.h" #include +#ifndef ENABLE_DSS_SNIPE +#include + #include #include +#else +#include "systempower1interface.h" +#endif #include +#include -#define LOCKSERVICE_PATH "/com/deepin/dde/LockService" -#define LOCKSERVICE_NAME "com.deepin.dde.LockService" -#define SECURITYENHANCE_PATH "/com/deepin/daemon/SecurityEnhance" -#define SECURITYENHANCE_NAME "com.deepin.daemon.SecurityEnhance" +#define SECURITY_ENHANCE_PATH "/com/deepin/daemon/SecurityEnhance" +#define SECURITY_ENHANCE_NAME "com.deepin.daemon.SecurityEnhance" +#ifndef ENABLE_DSS_SNIPE using PowerInter = com::deepin::system::Power; +#else +using PowerInter = org::deepin::dde::Power1; +#endif using namespace Auth; using namespace AuthCommon; DCORE_USE_NAMESPACE @@ -27,21 +44,23 @@ const int NUM_LOCK_UNKNOWN = 2; // 未知状态 GreeterWorker::GreeterWorker(SessionBaseModel *const model, QObject *parent) : AuthInterface(model, parent) - , m_greeter(new QLightDM::Greeter(this)) , m_authFramework(new DeepinAuthFramework(this)) - , m_lockInter(new DBusLockService(LOCKSERVICE_NAME, LOCKSERVICE_PATH, QDBusConnection::systemBus(), this)) + , m_greeter(new QLightDM::Greeter(this)) + , m_lockInter(new DBusLockService(DSS_DBUS::lockService, DSS_DBUS::lockServicePath, QDBusConnection::systemBus(), this)) + , m_systemDaemon(new QDBusInterface(DSS_DBUS::systemDaemonService, DSS_DBUS::systemDaemonPath, DSS_DBUS::systemDaemonService, QDBusConnection::systemBus(), this)) +#ifndef ENABLE_DSS_SNIPE , m_soundPlayerInter(new SoundThemePlayerInter("com.deepin.api.SoundThemePlayer", "/com/deepin/api/SoundThemePlayer", QDBusConnection::systemBus(), this)) +#endif , m_resetSessionTimer(new QTimer(this)) , m_limitsUpdateTimer(new QTimer(this)) , m_retryAuth(false) { #ifndef QT_DEBUG if (!m_greeter->connectSync()) { - qCritical() << "greeter connect fail !!!"; + qCritical() << "ERROR: greeter connect fail!"; exit(1); } #endif - checkDBusServer(m_accountsInter->isValid()); initConnections(); @@ -53,20 +72,28 @@ GreeterWorker::GreeterWorker(SessionBaseModel *const model, QObject *parent) //认证超时重启 m_resetSessionTimer->setInterval(15000); - if (QGSettings::isSchemaInstalled("com.deepin.dde.session-shell")) { - QGSettings gsetting("com.deepin.dde.session-shell", "/com/deepin/dde/session-shell/", this); - if (gsetting.keys().contains("authResetTime")) { - int resetTime = gsetting.get("auth-reset-time").toInt(); - if (resetTime > 0) - m_resetSessionTimer->setInterval(resetTime); - } +#ifndef ENABLE_DSS_SNIPE + if (m_gsettings != nullptr && m_gsettings->keys().contains("authResetTime")) { + int resetTime = m_gsettings->get("auth-reset-time").toInt(); + if (resetTime > 0) + m_resetSessionTimer->setInterval(resetTime); + } +#else + if (!m_dConfig) { + m_dConfig = DConfig::create("org.deepin.dde.session-shell", "org.deepin.dde.session-shell", QString(), this); + } + int resetTime = m_dConfig->value("authResetTime", 15000).toInt(); + if (resetTime > 0) { + m_resetSessionTimer->setInterval(resetTime); } +#endif m_resetSessionTimer->setSingleShot(true); - connect(m_resetSessionTimer, &QTimer::timeout, this, [=] { + connect(m_resetSessionTimer, &QTimer::timeout, this, [this] { + qCInfo(DDE_SHELL) << "Reset session time out"; endAuthentication(m_account, AT_All); m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); - destoryAuthentication(m_account); + destroyAuthentication(m_account); createAuthentication(m_account); }); } @@ -82,23 +109,46 @@ void GreeterWorker::initConnections() connect(m_greeter, &QLightDM::Greeter::showMessage, this, &GreeterWorker::showMessage); connect(m_greeter, &QLightDM::Greeter::authenticationComplete, this, &GreeterWorker::authenticationComplete); /* com.deepin.daemon.Accounts */ - connect(m_accountsInter, &AccountsInter::UserAdded, m_model, static_cast(&SessionBaseModel::addUser)); - connect(m_accountsInter, &AccountsInter::UserDeleted, m_model, static_cast(&SessionBaseModel::removeUser)); - // connect(m_accountsInter, &AccountsInter::UserListChanged, m_model, &SessionBaseModel::updateUserList); // UserListChanged信号的处理, 改用UserAdded和UserDeleted信号替代 + connect(m_accountsInter, &AccountsInter::UserAdded, this, [this](const QString &path) { + // Account接口中的path可能被不同用户复用,导致model中数据未更新 + qCInfo(DDE_SHELL) << "User add, path:" << path; + auto userPtr = m_model->findUserByPath(path); + if (userPtr) { + auto userName = userPtr->name(); + QString accountPath = m_accountsInter->FindUserByName(userName); + if (accountPath != path) { + // 查询结果空或者变动 + qCWarning(DDE_SHELL) << "users updated, force remove : " << path << userName; + m_model->removeUser(path); + } + } + m_model->addUser(path); + }); connect(m_accountsInter, &AccountsInter::UserDeleted, this, [this](const QString &path) { + qCInfo(DDE_SHELL) << "User delete, path:" << path; + // Account接口中的path可能被不同用户复用,导致model中数据未更新 + // 先remove + m_model->removeUser(path); + m_model->updateUserList(m_accountsInter->userList()); + if (path == m_model->currentUser()->path()) { - m_model->updateCurrentUser(m_lockInter->CurrentUser()); + if (!m_model->updateCurrentUser(m_lockInter->CurrentUser())) { + qCWarning(DDE_SHELL) << "updateCurrentUser failed"; + } m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); - destoryAuthentication(m_account); + destroyAuthentication(m_account); if (!m_model->currentUser()->isNoPasswordLogin()) { createAuthentication(m_model->currentUser()->name()); } else { m_model->setAuthType(AT_None); } +#ifndef ENABLE_DSS_SNIPE m_soundPlayerInter->PrepareShutdownSound(static_cast(m_model->currentUser()->uid())); +#else + prepareShutdownSound(); +#endif } }); - connect(m_loginedInter, &LoginedInter::LastLogoutUserChanged, m_model, static_cast(&SessionBaseModel::updateLastLogoutUser)); connect(m_loginedInter, &LoginedInter::UserListChanged, m_model, &SessionBaseModel::updateLoginedUserList); /* com.deepin.daemon.Authenticate */ connect(m_authFramework, &DeepinAuthFramework::FramworkStateChanged, m_model, &SessionBaseModel::updateFrameworkState); @@ -108,6 +158,15 @@ void GreeterWorker::initConnections() m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(account)); } }); + connect(m_authFramework, &DeepinAuthFramework::DeviceChanged, this, [this](const int type, const int state) { + qCInfo(DDE_SHELL) << "Device changed, type: " << type << ", state: " << state; + // 如果是单因或者多因且包含该类型认证,需要重新创建认证 + if (m_model->visible() && (!m_model->getAuthProperty().MFAFlag || (m_model->getAuthProperty().MFAFlag && (m_model->getAuthProperty().AuthType & type)))) { + endAuthentication(m_account, AT_All); + destroyAuthentication(m_account); + createAuthentication(m_account); + } + }); connect(m_authFramework, &DeepinAuthFramework::SupportedEncryptsChanged, m_model, &SessionBaseModel::updateSupportedEncryptionType); connect(m_authFramework, &DeepinAuthFramework::SupportedMixAuthFlagsChanged, m_model, &SessionBaseModel::updateSupportedMixAuthFlags); /* com.deepin.daemon.Authenticate.Session */ @@ -117,10 +176,14 @@ void GreeterWorker::initConnections() connect(m_authFramework, &DeepinAuthFramework::MFAFlagChanged, m_model, &SessionBaseModel::updateMFAFlag); connect(m_authFramework, &DeepinAuthFramework::PINLenChanged, m_model, &SessionBaseModel::updatePINLen); connect(m_authFramework, &DeepinAuthFramework::PromptChanged, m_model, &SessionBaseModel::updatePrompt); + connect(m_authFramework, &DeepinAuthFramework::SessionCreated, this, &GreeterWorker::onSessionCreated); + connect(m_authFramework, &DeepinAuthFramework::TokenAccountMismatch, this, &GreeterWorker::resetAuth); + /* org.freedesktop.login1.Session */ - connect(m_login1SessionSelf, &Login1SessionSelf::ActiveChanged, this, [=](bool active) { - qInfo() << "Login1SessionSelf::ActiveChanged:" << active; + connect(m_login1SessionSelf, &Login1SessionSelf::ActiveChanged, this, [this](bool active) { + qCInfo(DDE_SHELL) << "Login1SessionSelf::ActiveChanged:" << active; if (m_model->currentUser() == nullptr || m_model->currentUser()->name().isEmpty()) { + qCWarning(DDE_SHELL) << "Current user is invalid or current user's name is empty"; return; } if (active) { @@ -129,43 +192,72 @@ void GreeterWorker::initConnections() } } else { endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + destroyAuthentication(m_account); } }); + + connect(m_login1Inter, &DBusLogin1Manager::PrepareForSleep, this, [this](bool active) { + const bool sessionIsActive = m_login1SessionSelf->active(); + qDebug() << "Prepare for sleep, whether set dpms: " << (!active ? "on" : "off") + << ", curren session is active:" << sessionIsActive; + // session 未激活的时候使用 dde-wldpms 无效,且 dde-wldpms 无法收到 modeChanged 信号,会一直处于等待状态不退出 + if (sessionIsActive) + screenSwitchByWldpms(!active); + }); + /* org.freedesktop.login1.Manager */ - connect(m_login1Inter, &DBusLogin1Manager::PrepareForSleep, this, [=](bool isSleep) { - qInfo() << "DBusLogin1Manager::PrepareForSleep:" << isSleep; + connect(m_login1Inter, &DBusLogin1Manager::PrepareForSleep, this, [this](bool isSleep) { + qCInfo(DDE_SHELL) << "DBus login1 manager prepare for sleep:" << isSleep; // 登录界面待机或休眠时提供显示假黑屏,唤醒时显示正常界面 m_model->setIsBlackMode(isSleep); if (isSleep) { endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + destroyAuthentication(m_account); } else { - createAuthentication(m_model->currentUser()->name()); + if (!m_model->currentUser()->isNoPasswordLogin()) { + bool useOnekeylogin = DConfigHelper::instance()->getConfig("enableOneKeylogin", false).toBool(); + if (useOnekeylogin) { + // 当有一键登录的时候,需要保证一键登录插件中待机唤醒处理逻辑在此之前;否则greeter待机唤醒一键登录功能异常 + QTimer::singleShot(0, this, [this]{ + createAuthentication(m_model->currentUser()->name()); + }); + } else { + createAuthentication(m_model->currentUser()->name()); + } + } } }); connect(m_login1Inter, &DBusLogin1Manager::SessionRemoved, this, [this] { - qInfo() << "DBusLogin1Manager::SessionRemoved"; + qCInfo(DDE_SHELL) << "DBus login1 manager session removed"; if (m_model->updateCurrentUser(m_lockInter->CurrentUser())) { m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); - destoryAuthentication(m_account); + destroyAuthentication(m_account); if (!m_model->currentUser()->isNoPasswordLogin()) { createAuthentication(m_model->currentUser()->name()); } else { m_model->setAuthType(AT_None); } } +#ifndef ENABLE_DSS_SNIPE m_soundPlayerInter->PrepareShutdownSound(static_cast(m_model->currentUser()->uid())); +#else + prepareShutdownSound(); +#endif }); /* com.deepin.dde.LockService */ - connect(m_lockInter, &DBusLockService::UserChanged, this, [=](const QString &json) { - qInfo() << "DBusLockService::UserChanged:" << json; + connect(m_lockInter, &DBusLockService::UserChanged, this, [this](const QString &json) { + qCInfo(DDE_SHELL) << "User changed: " << json; // 如果是已登录用户则返回,否则已登录用户和未登录用户来回切换时会造成用户信息错误 std::shared_ptr user_ptr = m_model->json2User(json); if (!user_ptr || user_ptr->isLogin()) return; + if (user_ptr->name() == User().name()) { + qCWarning(DDE_SHELL) << "Avoid set invalid user from lockservice"; + return; + } + m_resetSessionTimer->stop(); m_model->updateCurrentUser(user_ptr); const QString &account = user_ptr->name(); @@ -173,13 +265,14 @@ void GreeterWorker::initConnections() emit m_model->authTypeChanged(AT_None); m_account = account; } - QTimer::singleShot(100, this, [ = ] { + QTimer::singleShot(100, this, [this] { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); }); }); /* model */ - connect(m_model, &SessionBaseModel::authTypeChanged, this, [=](const int type) { - qInfo() << "Auth type changed: " << type; + connect(m_model, &SessionBaseModel::authTypeChanged, this, [this](const AuthFlags type) { + qCInfo(DDE_SHELL) << "Auth type changed, incoming type:" << type + << ", mfa flag:" << m_model->getAuthProperty().MFAFlag; if (type > 0 && m_model->getAuthProperty().MFAFlag) { startAuthentication(m_account, m_model->getAuthProperty().AuthType); } @@ -187,9 +280,9 @@ void GreeterWorker::initConnections() }); connect(m_model, &SessionBaseModel::onPowerActionChanged, this, &GreeterWorker::doPowerAction); connect(m_model, &SessionBaseModel::currentUserChanged, this, &GreeterWorker::onCurrentUserChanged); - connect(m_model, &SessionBaseModel::visibleChanged, this, [=](bool visible) { + connect(m_model, &SessionBaseModel::visibleChanged, this, [this](bool visible) { if (visible) { - if (!m_model->isServerModel() + if (m_authFramework->isDAStartupCompleted() && !m_model->isServerModel() && (!m_model->currentUser()->isNoPasswordLogin() || m_model->currentUser()->expiredState() == User::ExpiredAlready)) { createAuthentication(m_model->currentUser()->name()); } @@ -197,65 +290,117 @@ void GreeterWorker::initConnections() m_resetSessionTimer->stop(); } }); - /* others */ - connect(KeyboardMonitor::instance(), &KeyboardMonitor::numlockStatusChanged, this, [=](bool on) { - saveNumlockState(m_model->currentUser(), on); + /* 数字键盘状态 */ + connect(KeyboardMonitor::instance(), &KeyboardMonitor::numLockStatusChanged, this, [this](bool on) { + saveNumLockState(m_model->currentUser(), on); }); + + connect(KeyboardMonitor::instance(), &KeyboardMonitor::initialized, this, [this] { + if (m_model) { + recoveryUserKBState(m_model->currentUser()); + } + }); + connect(m_limitsUpdateTimer, &QTimer::timeout, this, [this] { if (m_authFramework->isDeepinAuthValid()) m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_account)); }); // 等保服务开启/关闭时更新 - QDBusConnection::systemBus().connect(SECURITYENHANCE_NAME, SECURITYENHANCE_PATH, SECURITYENHANCE_NAME, + QDBusConnection::systemBus().connect(SECURITY_ENHANCE_NAME, SECURITY_ENHANCE_PATH, SECURITY_ENHANCE_NAME, "Receipt", this, SLOT(onReceiptChanged(bool))); + + connect(m_authFramework, &DeepinAuthFramework::startupCompleted, this, [this] { + /* com.deepin.daemon.Authenticate */ + m_model->updateFrameworkState(m_authFramework->GetFrameworkState()); + m_model->updateSupportedEncryptionType(m_authFramework->GetSupportedEncrypts()); + m_model->updateSupportedMixAuthFlags(m_authFramework->GetSupportedMixAuthFlags()); + m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); + + if (m_model->visible() && !m_model->isServerModel() + && (!m_model->currentUser()->isNoPasswordLogin() || m_model->currentUser()->expiredState() == User::ExpiredAlready)) { + createAuthentication(m_model->currentUser()->name()); + } + }); + + // 监听terminal锁定状态 + QDBusConnection::systemBus().connect(DSS_DBUS::accountsService, DSS_DBUS::accountsPath, "org.freedesktop.DBus.Properties", + "PropertiesChanged", this, SLOT(terminalLockedChanged(QDBusMessage))); + + connect(&SignalBridge::ref(), &SignalBridge::requestSendExtraInfo, this, &GreeterWorker::sendExtraInfo); } void GreeterWorker::initData() { - if (isSecurityEnhanceOpen()) + if (isSecurityEnhanceOpen()) { + qCInfo(DDE_SHELL) << "Security enhance is open"; m_model->setSEType(true); + } - /* com.deepin.daemon.Accounts */ - m_model->updateUserList(m_accountsInter->userList()); - m_model->updateLastLogoutUser(m_loginedInter->lastLogoutUser()); - m_model->updateLoginedUserList(m_loginedInter->userList()); - - /* com.deepin.udcp.iam */ - QDBusInterface ifc("com.deepin.udcp.iam", "/com/deepin/udcp/iam", "com.deepin.udcp.iam", QDBusConnection::systemBus(), this); - const bool allowShowCustomUser = valueByQSettings("", "loginPromptInput", false) || ifc.property("Enable").toBool(); - m_model->setAllowShowCustomUser(allowShowCustomUser); - - /* init current user */ - if (DSysInfo::deepinType() == DSysInfo::DeepinServer || m_model->allowShowCustomUser()) { - std::shared_ptr user(new User()); - m_model->setIsServerModel(DSysInfo::deepinType() == DSysInfo::DeepinServer); - m_model->addUser(user); - if (DSysInfo::deepinType() == DSysInfo::DeepinServer) { - m_model->updateCurrentUser(user); + auto list = m_accountsInter->userList(); + if (!list.isEmpty()) { + /* com.deepin.daemon.Accounts */ + m_model->updateUserList(list); + m_model->updateLoginedUserList(m_loginedInter->userList()); + + m_model->setUserlistVisible(valueByQSettings("", "userlist", true)); + /* com.deepin.udcp.iam */ + QDBusInterface ifc(DSS_DBUS::udcpIamService, DSS_DBUS::udcpIamPath, DSS_DBUS::udcpIamService, QDBusConnection::systemBus(), this); + const bool allowShowCustomUser = (!m_model->userlistVisible()) || valueByQSettings("", "loginPromptInput", false) || + ifc.property("Enable").toBool() || checkIsADDomain(); + m_model->setAllowShowCustomUser(allowShowCustomUser); + + /* init current user */ + if (DSysInfo::deepinType() == DSysInfo::DeepinServer || m_model->allowShowCustomUser()) { + // 如果是服务器版本或者loginPromptInput配置为true,默认显示空用户 + std::shared_ptr user(new User()); + m_model->setIsServerModel(DSysInfo::deepinType() == DSysInfo::DeepinServer); + m_model->addUser(user); + if (DSysInfo::deepinType() == DSysInfo::DeepinServer || valueByQSettings("", "loginPromptInput", false) || !m_model->userlistVisible()) { + m_model->updateCurrentUser(user); + } else { + /* com.deepin.dde.LockService */ + m_model->updateCurrentUser(m_lockInter->CurrentUser()); + } } else { /* com.deepin.dde.LockService */ m_model->updateCurrentUser(m_lockInter->CurrentUser()); } +#ifndef ENABLE_DSS_SNIPE + m_soundPlayerInter->PrepareShutdownSound(static_cast(m_model->currentUser()->uid())); +#else + prepareShutdownSound(); +#endif } else { - /* com.deepin.dde.LockService */ - m_model->updateCurrentUser(m_lockInter->CurrentUser()); + qCWarning(DDE_SHELL) << "dbus com.deepin.daemon.Accounts userList is empty, use ..."; + m_model->setAllowShowCustomUser(true); + std::shared_ptr user(new User()); + m_model->addUser(user); + m_model->updateCurrentUser(user); } - m_soundPlayerInter->PrepareShutdownSound(static_cast(m_model->currentUser()->uid())); /* com.deepin.daemon.Authenticate */ - if (m_authFramework->isDeepinAuthValid()) { + if (m_authFramework->isDAStartupCompleted() ) { m_model->updateFrameworkState(m_authFramework->GetFrameworkState()); m_model->updateSupportedEncryptionType(m_authFramework->GetSupportedEncrypts()); m_model->updateSupportedMixAuthFlags(m_authFramework->GetSupportedMixAuthFlags()); m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); } + + // 获取terminal锁定状态 + QDBusInterface accoutsInter(DSS_DBUS::accountsService, DSS_DBUS::accountsPath, DSS_DBUS::accountsService, QDBusConnection::systemBus(), this); + m_model->setTerminalLocked(accoutsInter.property("IsTerminalLocked").toBool()); } void GreeterWorker::initConfiguration() { +#ifndef ENABLE_DSS_SNIPE m_model->setAlwaysShowUserSwitchButton(getGSettings("", "switchuser").toInt() == AuthInterface::Always); m_model->setAllowShowUserSwitchButton(getGSettings("", "switchuser").toInt() == AuthInterface::Ondemand); +#else + m_model->setAlwaysShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Always); + m_model->setAllowShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Ondemand); +#endif checkPowerInfo(); @@ -265,11 +410,11 @@ void GreeterWorker::initConfiguration() // 当这个配置不存在是,如果是不是笔记本就打开小键盘,否则就关闭小键盘 0关闭键盘 1打开键盘 2默认值(用来判断是不是有这个key) if (m_model->currentUser() != nullptr && getNumLockState(m_model->currentUser()->name()) == NUM_LOCK_UNKNOWN) { - PowerInter powerInter("com.deepin.system.Power", "/com/deepin/system/Power", QDBusConnection::systemBus(), this); + PowerInter powerInter(DSS_DBUS::powerService, DSS_DBUS::powerPath, QDBusConnection::systemBus(), this); if (powerInter.hasBattery()) { - saveNumlockState(m_model->currentUser(), false); + saveNumLockState(m_model->currentUser(), false); } else { - saveNumlockState(m_model->currentUser(), true); + saveNumLockState(m_model->currentUser(), true); } } recoveryUserKBState(m_model->currentUser()); @@ -311,11 +456,19 @@ void GreeterWorker::doPowerAction(const SessionBaseModel::PowerAction action) */ void GreeterWorker::setCurrentUser(const std::shared_ptr user) { + // 不要把用于域用户UI控制的“...”用户写给后端 + if (user && user->name() == User().name()) { + qCWarning(DDE_SHELL) << "Avoid set invalid user to lockservice"; + return; + } + + qCInfo(DDE_SHELL) << "Set current user, user:" << user->name(); QJsonObject json; - json["AuthType"] = user->lastAuthType(); + json["AuthType"] = static_cast(user->lastAuthType()); json["Name"] = user->name(); json["Type"] = user->type(); json["Uid"] = static_cast(user->uid()); + json["LastCustomAuth"] = user->lastCustomAuth(); // 上一次认证通过自定义认证类型 m_lockInter->SwitchToUser(QString(QJsonDocument(json).toJson(QJsonDocument::Compact))).waitForFinished(); } @@ -327,37 +480,45 @@ void GreeterWorker::switchToUser(std::shared_ptr user) } return; } - qInfo() << "switch user from" << m_account << " to " << user->name() << user->uid() << user->isLogin(); + qCInfo(DDE_SHELL) << "Switch user from" << m_account + << ", to:" << user->name() + << ", user id:" << user->uid() + << ", is login:" << user->isLogin(); endAuthentication(m_account, AT_All); if (user->uid() == INT_MAX) { m_model->setAuthType(AT_None); } + + setCurrentUser(user); if (user->isLogin()) { // switch to user Xorg QProcess::startDetached("dde-switchtogreeter", QStringList() << user->name()); } else { - setCurrentUser(user); m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); - destoryAuthentication(m_account); + destroyAuthentication(m_account); m_model->updateCurrentUser(user); if (!user->isNoPasswordLogin()) { createAuthentication(user->name()); } else { m_model->setAuthType(AT_None); } +#ifndef ENABLE_DSS_SNIPE m_soundPlayerInter->PrepareShutdownSound(static_cast(m_model->currentUser()->uid())); +#else + prepareShutdownSound(); +#endif } } bool GreeterWorker::isSecurityEnhanceOpen() { - QDBusInterface securityEnhanceInterface(SECURITYENHANCE_NAME, - SECURITYENHANCE_PATH, - SECURITYENHANCE_NAME, + QDBusInterface securityEnhanceInterface(SECURITY_ENHANCE_NAME, + SECURITY_ENHANCE_PATH, + SECURITY_ENHANCE_NAME, QDBusConnection::systemBus()); QDBusReply reply = securityEnhanceInterface.call("Status"); if (!reply.isValid()) { - qWarning() << "get security enhance status error: " << reply.error(); + qCWarning(DDE_SHELL) << "Get security enhance status error: " << reply.error(); return false; } return reply.value() == "open" || reply.value() == "opening"; @@ -370,25 +531,45 @@ bool GreeterWorker::isSecurityEnhanceOpen() */ void GreeterWorker::createAuthentication(const QString &account) { - qInfo() << "GreeterWorker::createAuthentication:" << account; + qCInfo(DDE_SHELL) << "Create auth entication, account: " << account; + if (m_model->terminalLocked()) { + // 切换用户后,需要触发TerminalLocked信号 + m_model->sendTerminalLockedSignal(); + return; + } + m_account = account; if (account.isEmpty() || account == "...") { m_model->setAuthType(AT_None); return; } + // 如果验证会话已经存在,销毁后重新开启验证 + // TODO 这个处理办法稳健但是比较粗暴,后面需要结合DA梳理一下认证session创建、销毁和复用的时机,优化流程 + if (m_authFramework->authSessionExist(account)) { + endAuthentication(account, AT_All); + destroyAuthentication(account); + } + m_retryAuth = false; std::shared_ptr user_ptr = m_model->findUserByName(account); if (user_ptr) { user_ptr->updatePasswordExpiredInfo(); + } else { +#ifndef ENABLE_DSS_SNIPE + // 域管账户第一次登录时,后端还未提供账户信息,获取不到用户密码过期数据 + // 需要通过glibc接口读取 + updatePasswordExpiredStateBySPName(account); +#else + qCWarning(DDE_SHELL) << "createAuthentication: user not found in local model," + << "password expired info will NOT be synced. account:" << account; +#endif } + switch (m_model->getAuthProperty().FrameworkState) { case Available: m_authFramework->CreateAuthController(account, m_authFramework->GetSupportedMixAuthFlags(), Login); m_authFramework->SetAuthQuitFlag(account, DeepinAuthFramework::ManualQuit); - if (!m_authFramework->SetPrivilegesEnable(account, QString("/usr/sbin/lightdm"))) { - qWarning() << "Failed to set privileges!"; - } startGreeterAuth(account); break; default: @@ -403,12 +584,12 @@ void GreeterWorker::createAuthentication(const QString &account) * * @param account */ -void GreeterWorker::destoryAuthentication(const QString &account) +void GreeterWorker::destroyAuthentication(const QString &account) { - qDebug() << "GreeterWorker::destoryAuthentication:" << account; + qCInfo(DDE_SHELL) << "Destroy authentication, account:" << account; switch (m_model->getAuthProperty().FrameworkState) { case Available: - m_authFramework->DestoryAuthController(account); + m_authFramework->DestroyAuthController(account); break; default: break; @@ -422,16 +603,17 @@ void GreeterWorker::destoryAuthentication(const QString &account) * @param authType 认证类型(可传入一种或多种) * @param timeout 设定超时时间(默认 -1) */ -void GreeterWorker::startAuthentication(const QString &account, const int authType) +void GreeterWorker::startAuthentication(const QString &account, const AuthFlags authType) { - qDebug() << "GreeterWorker::startAuthentication:" << account << authType; + if (!m_model->currentUser()->allowToChangePassword()) { + qCInfo(DDE_SHELL) << "Authentication exit because of user's authority"; + return; + } + qCInfo(DDE_SHELL) << "Start authentication, account:" << account << ", auth type:" << authType; switch (m_model->getAuthProperty().FrameworkState) { case Available: m_authFramework->StartAuthentication(account, authType, -1); - // 如果密码被锁定了,lightdm会停止验证,在开启验证的时候需要判断一下lightdm是否在验证中。 - if (!m_greeter->inAuthentication()) - startGreeterAuth(account); - + startGreeterAuth(account); break; default: startGreeterAuth(account); @@ -446,9 +628,9 @@ void GreeterWorker::startAuthentication(const QString &account, const int authTy * @param authType 认证类型 * @param token 密文 */ -void GreeterWorker::sendTokenToAuth(const QString &account, const int authType, const QString &token) +void GreeterWorker::sendTokenToAuth(const QString &account, const AuthType authType, const QString &token) { - qDebug() << "GreeterWorker::sendTokenToAuth:" << account << authType; + qCInfo(DDE_SHELL) << "Send token:" << account << ", auth type:" << authType; switch (m_model->getAuthProperty().FrameworkState) { case Available: if (AT_PAM == authType) { @@ -472,9 +654,10 @@ void GreeterWorker::sendTokenToAuth(const QString &account, const int authType, * @param account 账户 * @param authType 认证类型 */ -void GreeterWorker::endAuthentication(const QString &account, const int authType) +void GreeterWorker::endAuthentication(const QString &account, const AuthFlags authType) { - qDebug() << "GreeterWorker::endAuthentication:" << account << authType; + qCInfo(DDE_SHELL) << "End authentication, account:" << account << ", auth type:" << authType; + switch (m_model->getAuthProperty().FrameworkState) { case Available: if (authType == AT_All) @@ -492,45 +675,69 @@ void GreeterWorker::endAuthentication(const QString &account, const int authType * * @param account */ -void GreeterWorker::checkAccount(const QString &account) +void GreeterWorker::checkAccount(const QString &account, bool switchUser) { - qDebug() << "GreeterWorker::checkAccount:" << account; - if (m_greeter->authenticationUser() == account) { - return; - } - - std::shared_ptr user_ptr = m_model->findUserByName(account); + qCInfo(DDE_SHELL) << "Check account, account: " << account; + const auto &originalUsePtr = m_model->findUserByName(account); + std::shared_ptr user_ptr = originalUsePtr; // 当用户登录成功后,判断用户输入帐户有效性逻辑改为后端去做处理 const QString userPath = m_accountsInter->FindUserByName(account); if (userPath.startsWith("/")) { user_ptr = std::make_shared(userPath); - // 对于没有设置密码的账户,直接认定为错误账户 if (!user_ptr->isPasswordValid()) { - qWarning() << userPath; + qCWarning(DDE_SHELL) << "The user's password is invalid, user path: " << userPath; + emit m_model->accountError(); emit m_model->authFailedTipsMessage(tr("Wrong account")); m_model->setAuthType(AT_None); return; } + +#ifdef ENABLE_DSS_SNIPE + // 新发现的用户(如域管用户首次登录),加入本地 model, + // 确保后续 createAuthentication 中 findUserByName 能找到 + if (!originalUsePtr) { + m_model->addUser(userPath); + } +#endif } else if (!user_ptr) { // 判断账户第一次登录时的有效性 std::string str = account.toStdString(); passwd *pw = getpwnam(str.c_str()); if (pw) { QString userName = pw->pw_name; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QString userFullName = userName.left(userName.indexOf(QString("@"))); +#else QString userFullName = userName.leftRef(userName.indexOf(QString("@"))).toString(); +#endif user_ptr = std::make_shared(INT_MAX - 1); - dynamic_cast(user_ptr.get())->setName(userName); dynamic_cast(user_ptr.get())->setFullName(userFullName); } else { - qWarning() << userPath; + qCWarning(DDE_SHELL) << "Password is null, user path: " << userPath; + emit m_model->accountError(); emit m_model->authFailedTipsMessage(tr("Wrong account")); m_model->setAuthType(AT_None); return; } } + // m_greeter->cancelAuthentication后m_greeter的数据不会发生改变,当前账户如果是无密码登陆则不需要判断m_greeter认证数据 + if (m_greeter->authenticationUser() == account && m_account == account && !user_ptr->isNoPasswordLogin()) { + qCInfo(DDE_SHELL) << "The current user is the incoming user, do not check again"; + return; + } + + // 如果用户已经登录了,直接切换用户 + if (switchUser && originalUsePtr && originalUsePtr->isLogin() && user_ptr) { + qCInfo(DDE_SHELL) << "Current user is already logged in"; + Q_EMIT m_model->checkAccountFinished(); + user_ptr->updateLoginState(true); // 初始化 NativeUser 的时候没有处理登录状态 + switchToUser(user_ptr); + return; + } + m_model->updateCurrentUser(user_ptr); if (user_ptr->isNoPasswordLogin()) { if (user_ptr->expiredState() == User::ExpiredAlready) { @@ -541,19 +748,44 @@ void GreeterWorker::checkAccount(const QString &account) m_resetSessionTimer->stop(); endAuthentication(m_account, AT_All); m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); - destoryAuthentication(m_account); + destroyAuthentication(m_account); createAuthentication(user_ptr->name()); } } +void GreeterWorker::checkSameNameAccount(const QString &account, bool switchUser) +{ + qCInfo(DDE_SHELL) << "Start check same name account, name: " << account; + QDBusInterface ifc(DSS_DBUS::udcpIamService, DSS_DBUS::udcpIamPath, DSS_DBUS::udcpIamService, QDBusConnection::systemBus()); + QDBusPendingReply reply = ifc.asyncCall(QStringLiteral("GetPwName"), account); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, [this, account, switchUser, reply, watcher] { + if (reply.error().message().isEmpty()) { + const auto &originalUsePtr = m_model->findUserByName(account); + const QString &userDetail = reply.value(); + if (originalUsePtr && !originalUsePtr->isDomainUser() && !userDetail.isEmpty()) { + qCInfo(DDE_SHELL) << "Find same name account, user detail: " << userDetail; + Q_EMIT requestShowUsersWithTheSameName(account, userDetail); + } else { + qCInfo(DDE_SHELL) << "Not find same name account"; + checkAccount(account, switchUser); + } + } else { + qCWarning(DDE_SHELL) << "Check same name account failed, error:" << reply.error().message(); + checkAccount(account, switchUser); + } + watcher->deleteLater(); + }); +} + void GreeterWorker::checkDBusServer(bool isValid) { if (isValid) { m_accountsInter->userList(); } else { // FIXME: 我不希望这样做,但是QThread::msleep会导致无限递归 - QTimer::singleShot(300, this, [=] { - qWarning() << "com.deepin.daemon.Accounts is not start, rechecking!"; + QTimer::singleShot(300, this, [this] { + qCWarning(DDE_SHELL) << "com.deepin.daemon.Accounts is not start, rechecking!"; checkDBusServer(m_accountsInter->isValid()); }); } @@ -567,7 +799,8 @@ void GreeterWorker::checkDBusServer(bool isValid) */ void GreeterWorker::showPrompt(const QString &text, const QLightDM::Greeter::PromptType type) { - qInfo() << "Greeter prompt:" << text << "type:" << type; + qCInfo(DDE_SHELL) << "Greeter prompt: " << text << ", type:" << type; + m_model->setLightdmPamStarted(true); switch (type) { case QLightDM::Greeter::PromptTypeSecret: m_retryAuth = true; @@ -587,7 +820,8 @@ void GreeterWorker::showPrompt(const QString &text, const QLightDM::Greeter::Pro */ void GreeterWorker::showMessage(const QString &text, const QLightDM::Greeter::MessageType type) { - qInfo() << "Greeter message:" << text << "type:" << type; + qCInfo(DDE_SHELL) << "Greeter message:" << text << ", type:" << type; + m_model->setLightdmPamStarted(true); switch (type) { case QLightDM::Greeter::MessageTypeInfo: m_model->updateAuthState(AT_PAM, AS_Prompt, text); @@ -605,7 +839,7 @@ void GreeterWorker::showMessage(const QString &text, const QLightDM::Greeter::Me void GreeterWorker::authenticationComplete() { const bool result = m_greeter->isAuthenticated(); - qInfo() << "Authentication result:" << result << "retryAuth" << m_retryAuth; + qCInfo(DDE_SHELL) << "Authentication result:" << result << ", retry auth" << m_retryAuth; if (!result) { if (m_retryAuth && !m_model->getAuthProperty().MFAFlag) { @@ -632,44 +866,61 @@ void GreeterWorker::authenticationComplete() break; } - qInfo() << "start session = " << m_model->sessionKey(); +#ifndef ENABLE_DSS_SNIPE + DDE_EventLogger::EventLoggerData data; + data.tid = EVENT_LOGGER_GREETER_LOGIN; + data.event = "startup"; + data.target = "dde-session-shell"; + data.message = {{"startup", "authenticationComplete"}, {"result", QString::number(result)}}; + DDE_EventLogger::EventLogger::instance().writeEventLog(data); +#endif - auto startSessionSync = [=]() { - setCurrentUser(m_model->currentUser()); - m_greeter->startSessionSync(m_model->sessionKey()); - }; + qCInfo(DDE_SHELL) << "Start session: " << m_model->sessionKey(); emit requestUpdateBackground(m_model->currentUser()->greeterBackground()); -#ifndef DISABLE_LOGIN_ANI - QTimer::singleShot(1000, this, startSessionSync); -#else - startSessionSync(); -#endif + setCurrentUser(m_model->currentUser()); + m_greeter->startSessionSync(m_model->sessionKey()); endAuthentication(m_account, AT_All); - destoryAuthentication(m_account); + destroyAuthentication(m_account); + + //清理所有TTY输出 + QDBusReply reply = m_systemDaemon->call("ClearTtys"); + if (!reply.isValid()) { + qCWarning(DDE_SHELL) << "Clear ttys failed, error messages: " << reply.error().message(); + }; } void GreeterWorker::onAuthFinished() { - qInfo() << "GreeterWorker::onAuthFinished"; + qCInfo(DDE_SHELL) << "Auth finished"; if (m_greeter->inAuthentication()) { m_greeter->respond(m_authFramework->AuthSessionPath(m_account) + QString(";") + m_password); +#ifndef ENABLE_DSS_SNIPE + updatePasswordExpiredStateBySPName(m_account); if (m_model->currentUser()->expiredState() == User::ExpiredAlready) { changePasswd(); } +#else + if (m_model->currentUser()) { + m_model->currentUser()->updatePasswordExpiredInfo(); + if (m_model->currentUser()->expiredState() == User::ExpiredAlready) { + changePasswd(); + } + } +#endif } else { - qWarning() << "The lightdm is not in authentication!"; + qCWarning(DDE_SHELL) << "The lightdm is not in authentication!"; } } void GreeterWorker::onAuthStateChanged(const int type, const int state, const QString &message) { - qDebug() << "GreeterWorker::onAuthStateChanged:" << type << state << message; + qCInfo(DDE_SHELL) << "Auth type:" << type << ", state:" << state << ", message:" << message; if (m_model->getAuthProperty().MFAFlag) { if (type == AT_All) { switch (state) { case AS_Success: - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); m_resetSessionTimer->stop(); if (m_greeter->inAuthentication()) { m_greeter->respond(m_authFramework->AuthSessionPath(m_account) + QString(";") + m_password); @@ -677,12 +928,12 @@ void GreeterWorker::onAuthStateChanged(const int type, const int state, const QS changePasswd(); } } else { - qWarning() << "The lightdm is not in authentication!"; + qCWarning(DDE_SHELL) << "The lightdm is not in authentication!"; } break; case AS_Cancel: - m_model->updateAuthState(type, state, message); - destoryAuthentication(m_account); + m_model->updateAuthState(AuthType(type), AuthState(state), message); + destroyAuthentication(m_account); break; default: break; @@ -692,45 +943,50 @@ void GreeterWorker::onAuthStateChanged(const int type, const int state, const QS case AS_Success: if (m_model->currentModeState() != SessionBaseModel::ResetPasswdMode) m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); - m_resetSessionTimer->start(); - m_model->updateAuthState(type, state, message); + + // 处于序列化多因认证过程中时不要重置认证 + if (MFASequenceControl::instance().currentAuthType() == AuthType::AT_None) { + m_resetSessionTimer->start(); + } + + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; case AS_Failure: if (m_model->currentModeState() != SessionBaseModel::ResetPasswdMode) { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); // 人脸和虹膜需要手动重启验证 if (!m_model->currentUser()->limitsInfo(type).locked && type != AT_Face && type != AT_Iris) { QTimer::singleShot(50, this, [this, type] { - startAuthentication(m_account, type); + startAuthentication(m_account, AuthType(type)); }); } QTimer::singleShot(50, this, [=] { - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); }); break; case AS_Locked: if (m_model->currentModeState() != SessionBaseModel::ResetPasswdMode) m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); // TODO: 信号时序问题,考虑优化,Bug 89056 QTimer::singleShot(50, this, [=] { - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); }); break; case AS_Timeout: case AS_Error: - m_model->updateAuthState(type, state, message); - endAuthentication(m_account, type); + m_model->updateAuthState(AuthType(type), AuthState(state), message); + endAuthentication(m_account, AuthType(type)); break; case AS_Unlocked: m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; default: - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); break; } } @@ -741,26 +997,36 @@ void GreeterWorker::onAuthStateChanged(const int type, const int state, const QS m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); m_model->updateLimitedInfo(m_authFramework->GetLimitedInfo(m_model->currentUser()->name())); - m_model->updateAuthState(type, state, message); + m_model->updateAuthState(AuthType(type), AuthState(state), message); switch (state) { case AS_Success: - if (type == AT_Face || type == AT_Iris) - m_resetSessionTimer->start(); + if (m_model->currentUser()->isLdapUser() && type != AT_Custom && type != AT_All) { + auto loginType = LPUtil::loginType(); + if (loginType == LPUtil::Type::CLT_MFA) { + m_resetSessionTimer->setInterval(LPUtil::sessionTimeout()); + m_resetSessionTimer->start(); + break; + } + } + if (type == AT_Face || type == AT_Iris) { + m_resetSessionTimer->setInterval(DEFAULT_SESSION_TIMEOUT); + m_resetSessionTimer->start(); + } break; case AS_Failure: if (AT_All != type) { - endAuthentication(m_account, type); + endAuthentication(m_account, AuthType(type)); // 人脸和虹膜需要手动重新开启验证 if (!m_model->currentUser()->limitsInfo(type).locked && type != AT_Face && type != AT_Iris) { QTimer::singleShot(50, this, [this, type] { - startAuthentication(m_account, type); + startAuthentication(m_account, AuthType(type)); }); } } break; case AS_Cancel: - destoryAuthentication(m_account); + destroyAuthentication(m_account); break; default: break; @@ -779,11 +1045,22 @@ void GreeterWorker::onCurrentUserChanged(const std::shared_ptr &user) { recoveryUserKBState(user); loadTranslation(user->locale()); + // 账户在变换的时候需要通知lockservice + setCurrentUser(user); + emit requestUpdateBackground(m_model->currentUser()->greeterBackground()); } -void GreeterWorker::saveNumlockState(std::shared_ptr user, bool on) +void GreeterWorker::onSessionCreated() { - QStringList list = getDConfigValue(getDefaultConfigFileName(), "numLockState", QStringList()).toStringList(); + qCInfo(DDE_SHELL) << "Set privileges enable"; + if (!m_authFramework->SetPrivilegesEnable(m_account, QString("/usr/sbin/lightdm"))) { + qCWarning(DDE_SHELL) << "Failed to set privileges!"; + } +} + +void GreeterWorker::saveNumLockState(std::shared_ptr user, bool on) +{ + QStringList list = DConfigHelper::instance()->getConfig("numLockState", QStringList()).toStringList(); const QString &userName = user->name(); // 移除当前用户的记录 @@ -797,12 +1074,12 @@ void GreeterWorker::saveNumlockState(std::shared_ptr user, bool on) // 插入当前用户的记录 list.append(user->name() + ":" + (on ? "True" : "False")); - setDConfigValue(getDefaultConfigFileName(), "numLockState", list); + DConfigHelper::instance()->setConfig("numLockState", list); } int GreeterWorker::getNumLockState(const QString &userName) { - QStringList list = getDConfigValue(getDefaultConfigFileName(), "numLockState", QStringList()).toStringList(); + QStringList list = DConfigHelper::instance()->getConfig("numLockState", QStringList()).toStringList(); for (const QString &numLockState : list) { QStringList tmpList = numLockState.split(":"); @@ -816,23 +1093,21 @@ int GreeterWorker::getNumLockState(const QString &userName) void GreeterWorker::recoveryUserKBState(std::shared_ptr user) { - //FIXME(lxz) - // PowerInter powerInter("com.deepin.system.Power", "/com/deepin/system/Power", QDBusConnection::systemBus(), this); - // const BatteryPresentInfo info = powerInter.batteryIsPresent(); - // const bool defaultValue = !info.values().first(); if (user.get() == nullptr) return; const bool enabled = getNumLockState(user->name()) == NUM_UNLOCKED; - qWarning() << "restore numlock state to " << enabled; + qCWarning(DDE_SHELL) << "Restore numlock state to " << enabled; // Resync numlock light with numlock status - bool cur_numlock = KeyboardMonitor::instance()->isNumlockOn(); - KeyboardMonitor::instance()->setNumlockStatus(!cur_numlock); - KeyboardMonitor::instance()->setNumlockStatus(cur_numlock); + if (!m_model->isUseWayland()) { + bool currentNumLock = KeyboardMonitor::instance()->isNumLockOn(); + KeyboardMonitor::instance()->setNumLockStatus(!currentNumLock); + KeyboardMonitor::instance()->setNumLockStatus(currentNumLock); + } - KeyboardMonitor::instance()->setNumlockStatus(enabled); + KeyboardMonitor::instance()->setNumLockStatus(enabled); } void GreeterWorker::restartResetSessionTimer() @@ -844,11 +1119,152 @@ void GreeterWorker::restartResetSessionTimer() void GreeterWorker::startGreeterAuth(const QString &account) { - m_greeter->authenticate(account); + std::shared_ptr user_ptr = m_model->findUserByName(account); + // m_greeter->cancelAuthentication后m_greeter的数据不会发生改变,当前账户如果是无密码登陆则不需要判断m_greeter认证数据 + if (!m_greeter->inAuthentication() || m_greeter->authenticationUser() != account || (user_ptr && user_ptr->isNoPasswordLogin())) { + m_greeter->authenticate(account); + } else { + qCInfo(DDE_SHELL) << "Lightdm is in authentication, won't do it again, account: " << account; + } } void GreeterWorker::changePasswd() { + qCInfo(DDE_SHELL) << "Change password"; m_model->updateMFAFlag(false); m_model->setAuthType(AT_PAM); } + +void GreeterWorker::screenSwitchByWldpms(bool active) +{ + qDebug() << "Greeter worker screen switch by Wldpms:" << active; + QStringList arguments; + arguments << "-s"; + if (active) { + arguments << "on"; + } else { + arguments << "off"; + } + QProcess::startDetached("dde_wldpms", arguments); +} + +void GreeterWorker::updatePasswordExpiredStateBySPName(const QString &account) +{ + std::string str = account.toStdString(); + spwd *pw = getspnam(str.c_str()); + + if (pw) { + const int secondsPerDay = 60 * 60 * 24; + + long int spMax = pw->sp_max; + long int spWarn = pw->sp_warn; + long int spLastChg = pw->sp_lstchg; + + User::ExpiredState state = User::ExpiredNormal; + int days = 0; + + if (spLastChg == 0) { + // expired + state = User::ExpiredAlready; + days = 0; + } + + if (spMax == -1) { + // never expired + state = User::ExpiredNormal; + days = -1; + } + + int curDays = QDateTime::currentSecsSinceEpoch() / secondsPerDay; + int daysLeft = spLastChg + spMax - curDays; + + if (daysLeft < 0) { + state = User::ExpiredAlready; + days = daysLeft; + } else if (spWarn > daysLeft) { + state = User::ExpiredSoon; + days = daysLeft; + } + if (m_model->currentUser()) { + m_model->currentUser()->updatePasswordExpiredState(state, days); + } + } +} + +void GreeterWorker::terminalLockedChanged(const QDBusMessage &msg) +{ + QList arguments = msg.arguments(); + if (arguments.size() != 3) { + qCWarning(DDE_SHELL) << "Terminal locked changed invalid arguments size, size: " << arguments.size(); + return; + } + + QString interfaceName = arguments.at(0).toString(); + if (interfaceName != QString("com.deepin.daemon.Accounts")){ + return; + } + + QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); + if (changedProps.contains("IsTerminalLocked")) { + bool locked = changedProps.value("IsTerminalLocked").toBool(); + qCInfo(DDE_SHELL) << "Terminal locked changed, locked: " << locked; + m_model->setTerminalLocked(locked); + + if (!locked) { + createAuthentication(m_model->currentUser()->name()); + } + } +} + +void GreeterWorker::resetAuth(const QString &account) +{ + qCWarning(DDE_SHELL) << "reset auth for user : " << account; + if (account.isEmpty()) { + return; + } + + endAuthentication(account, AT_All); + m_model->updateAuthState(AT_All, AS_Cancel, "Cancel"); + destroyAuthentication(account); + createAuthentication(account); +} + +void GreeterWorker::onNoPasswordLoginChanged(const QString &account, bool noPassword) +{ + if(m_model->currentUser()->name() == account && m_greeter->authenticationUser() == account) { + + if (noPassword && m_greeter->inAuthentication()) { + m_greeter->cancelAuthentication(); + return; + } + + if (!noPassword && !m_greeter->inAuthentication()) { + createAuthentication(account); + } + } +} + +#ifdef ENABLE_DSS_SNIPE +void GreeterWorker::prepareShutdownSound() +{ + QDBusInterface soundPlayerInter("org.deepin.dde.SoundThemePlayer1", "/org/deepin/dde/SoundThemePlayer1", + "org.deepin.dde.SoundThemePlayer1", QDBusConnection::systemBus()); + if (!soundPlayerInter.isValid() || !m_model->currentUser()) { + qCWarning(DDE_SHELL) << "Sound player interface is not valid or current user is null:" << soundPlayerInter.isValid(); + return; + } + + //soundPlayerInter.call("PrepareShutdownSound", static_cast(m_model->currentUser()->uid())); +} +#endif + +void GreeterWorker::sendExtraInfo(const QString &account, AuthCommon::AuthType authType, const QString &info) +{ + switch (m_model->getAuthProperty().FrameworkState) { + case Available: + m_authFramework->sendExtraInfo(account, authType, info); + break; + default: + break; + } +} diff --git a/src/lightdm-deepin-greeter/greeterworker.h b/src/lightdm-deepin-greeter/greeterworker.h index f22f71ff..899ee135 100644 --- a/src/lightdm-deepin-greeter/greeterworker.h +++ b/src/lightdm-deepin-greeter/greeterworker.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef GREETERWORKEK_H #define GREETERWORKEK_H @@ -11,9 +15,11 @@ #include #include +#ifndef ENABLE_DSS_SNIPE #include using SoundThemePlayerInter = com::deepin::api::SoundThemePlayer; +#endif class GreeterWorker : public Auth::AuthInterface { @@ -36,23 +42,30 @@ class GreeterWorker : public Auth::AuthInterface void requestUpdateBackground(const QString &path); void requestShowPrompt(const QString &prompt); void requestShowMessage(const QString &message); + void requestShowUsersWithTheSameName(const QString nativeUserName, const QString &doMainAccountDetail); public slots: /* New authentication framework */ void createAuthentication(const QString &account); - void destoryAuthentication(const QString &account); - void startAuthentication(const QString &account, const int authType); - void endAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); + void destroyAuthentication(const QString &account); + void startAuthentication(const QString &account, const AuthFlags authType); + void endAuthentication(const QString &account, const AuthFlags authType); + void sendTokenToAuth(const QString &account, const AuthType authType, const QString &token); - void checkAccount(const QString &account); + void checkAccount(const QString &account, bool switchUser); + void checkSameNameAccount(const QString &account, bool switchUser); void restartResetSessionTimer(); void onAuthFinished(); + void onNoPasswordLoginChanged(const QString &account, bool noPassword); private slots: void onAuthStateChanged(const int type, const int state, const QString &message); void onReceiptChanged(bool state); void onCurrentUserChanged(const std::shared_ptr &user); + void onSessionCreated(); + void terminalLockedChanged(const QDBusMessage &msg); + void resetAuth(const QString &); + void sendExtraInfo(const QString &account, AuthCommon::AuthType authType, const QString &info); private: void initConnections(); @@ -66,17 +79,25 @@ private slots: void showPrompt(const QString &text, const QLightDM::Greeter::PromptType type); void showMessage(const QString &text, const QLightDM::Greeter::MessageType type); void authenticationComplete(); - void saveNumlockState(std::shared_ptr user, bool on); + void saveNumLockState(std::shared_ptr user, bool on); int getNumLockState(const QString &userName); void recoveryUserKBState(std::shared_ptr user); void startGreeterAuth(const QString &account = QString()); void changePasswd(); + void screenSwitchByWldpms(bool active); + void updatePasswordExpiredStateBySPName(const QString &account); +#ifdef ENABLE_DSS_SNIPE + void prepareShutdownSound(); +#endif private: - QLightDM::Greeter *m_greeter; DeepinAuthFramework *m_authFramework; + QLightDM::Greeter *m_greeter; DBusLockService *m_lockInter; + QDBusInterface *m_systemDaemon; +#ifndef ENABLE_DSS_SNIPE SoundThemePlayerInter *m_soundPlayerInter; +#endif QTimer *m_resetSessionTimer; QTimer *m_limitsUpdateTimer; QString m_account; diff --git a/src/lightdm-deepin-greeter/logincontent.cpp b/src/lightdm-deepin-greeter/logincontent.cpp index 392dc339..60580ca1 100644 --- a/src/lightdm-deepin-greeter/logincontent.cpp +++ b/src/lightdm-deepin-greeter/logincontent.cpp @@ -1,32 +1,38 @@ -/* - * Copyright (C) 2011 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: justforlxz - * - * Maintainer: justforlxz - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "logincontent.h" #include "logintipswindow.h" #include "sessionwidget.h" #include "controlwidget.h" -LoginContent::LoginContent(SessionBaseModel *const model, QWidget *parent) - : LockContent(model, parent) +LoginContent::LoginContent(QWidget *parent) + : LockContent(parent) + , m_usersWithTheSameName(nullptr) { + +} + +LoginContent *LoginContent::instance() +{ + static LoginContent* loginContent = nullptr; + if (!loginContent) { + loginContent = new LoginContent; + } + + return loginContent; +} + +void LoginContent::init(SessionBaseModel *model) +{ + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + LockContent::init(model); setAccessibleName("LoginContent"); m_sessionFrame = new SessionWidget; @@ -37,9 +43,9 @@ LoginContent::LoginContent(SessionBaseModel *const model, QWidget *parent) m_loginTipsWindow = new LoginTipsWindow; connect(m_loginTipsWindow, &LoginTipsWindow::requestClosed, m_model, &SessionBaseModel::tipsShowed); - connect(m_sessionFrame, &SessionWidget::hideFrame, this, &LockContent::restoreMode); + connect(m_sessionFrame, &SessionWidget::notifyHideSessionFrame, this, &LockContent::restoreMode); connect(m_sessionFrame, &SessionWidget::sessionChanged, this, &LockContent::restoreMode); - connect(m_controlWidget, &ControlWidget::requestSwitchSession, this, [ = ] { + connect(m_controlWidget, &ControlWidget::requestSwitchSession, this, [this] { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::SessionMode); }); connect(m_model, &SessionBaseModel::onSessionKeyChanged, m_controlWidget, &ControlWidget::chooseToSession); @@ -58,8 +64,13 @@ void LoginContent::onCurrentUserChanged(std::shared_ptr user) void LoginContent::onStatusChanged(SessionBaseModel::ModeStatus status) { + qCInfo(DDE_SHELL) << "Status changed, status" << status << ", current status: " << m_currentModeStatus; switch (status) { case SessionBaseModel::ModeStatus::SessionMode: + if (m_currentModeStatus == status) + break; + + m_currentModeStatus = status; pushSessionFrame(); break; default: @@ -97,3 +108,19 @@ void LoginContent::popTipsFrame() setBottomFrameVisible(true); LockContent::onStatusChanged(m_model->currentModeState()); } + +void LoginContent::showUsersWithTheSameName(const QString &nativeUserName, const QString &doMainAccountDetail) +{ + if (!m_usersWithTheSameName) { + m_usersWithTheSameName = new UsersWithTheSameName(m_model); + connect(m_usersWithTheSameName, &UsersWithTheSameName::requestCheckAccount, this, &LoginContent::requestCheckAccount); + connect(m_usersWithTheSameName, &UsersWithTheSameName::clicked, this, &LoginContent::restoreMode); + } + + if (!m_usersWithTheSameName->findUsers(nativeUserName, doMainAccountDetail)) + return; + m_model->setCurrentModeState(SessionBaseModel::SelectSameNameUserMode); + QSize size = getCenterContentSize(); + m_usersWithTheSameName->setFixedSize(size); + setCenterContent(m_usersWithTheSameName); +} diff --git a/src/lightdm-deepin-greeter/logincontent.h b/src/lightdm-deepin-greeter/logincontent.h index b5cf7b0f..0c792684 100644 --- a/src/lightdm-deepin-greeter/logincontent.h +++ b/src/lightdm-deepin-greeter/logincontent.h @@ -1,28 +1,12 @@ -/* - * Copyright (C) 2011 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: justforlxz - * - * Maintainer: justforlxz - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGINCONTENT_H #define LOGINCONTENT_H #include "lockcontent.h" +#include "userswiththesamename.h" class SessionWidget; class LoginTipsWindow; @@ -30,19 +14,23 @@ class LoginTipsWindow; class LoginContent : public LockContent { Q_OBJECT -public: - explicit LoginContent(SessionBaseModel *const model, QWidget *parent = nullptr); +public: + explicit LoginContent(QWidget *parent = nullptr); + static LoginContent *instance(); + void init(SessionBaseModel *model); void onCurrentUserChanged(std::shared_ptr user) override; void onStatusChanged(SessionBaseModel::ModeStatus status) override; void pushSessionFrame(); void pushTipsFrame(); void popTipsFrame(); + void showUsersWithTheSameName(const QString &nativeUserName, const QString &doMainAccountDetail); private: SessionWidget *m_sessionFrame; LoginTipsWindow *m_loginTipsWindow; bool m_showTipsWidget = true; + UsersWithTheSameName *m_usersWithTheSameName; }; #endif // LOGINCONTENT_H diff --git a/src/lightdm-deepin-greeter/logintipswindow.cpp b/src/lightdm-deepin-greeter/logintipswindow.cpp index 808e2196..1d117654 100644 --- a/src/lightdm-deepin-greeter/logintipswindow.cpp +++ b/src/lightdm-deepin-greeter/logintipswindow.cpp @@ -1,22 +1,7 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: chengbo - * - * Maintainer: chengbo - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "logintipswindow.h" #include "constants.h" @@ -25,10 +10,8 @@ #include #include #include -#include #include #include -#include DWIDGET_USE_NAMESPACE LoginTipsWindow::LoginTipsWindow(QWidget *parent) @@ -56,7 +39,7 @@ void LoginTipsWindow::initUI() m_content->setAlignment(Qt::AlignCenter); m_content->setTextFormat(Qt::TextFormat::PlainText); - // 获取/usr/share/dde-session-shell/dde-session-shell.conf 配置信息 + // 获取 session_ui_configs 中的 dde-session-shell.conf 配置信息 m_contentString = findValueByQSettings(DDESESSIONCC::session_ui_configs, "Greeter", "tipsContent", ""); m_content->setText(m_contentString); @@ -75,7 +58,7 @@ void LoginTipsWindow::initUI() m_tipLabel->setAlignment(Qt::AlignCenter); m_tipLabel->setTextFormat(Qt::TextFormat::PlainText); - // 获取/usr/share/dde-session-shell/dde-session-shell.conf 配置信息 + // 获取 session_ui_configs 中的 dde-session-shell.conf 配置信息 m_tipString = findValueByQSettings(DDESESSIONCC::session_ui_configs, "Greeter", "tipsTitle", ""); m_tipLabel->setText(m_tipString); @@ -96,7 +79,7 @@ void LoginTipsWindow::initUI() m_mainLayout->addStretch(); setLayout(m_mainLayout); - connect(m_btn, &QPushButton::clicked, this, [=] { + connect(m_btn, &QPushButton::clicked, this, [this] { // 点击确认后打开登录界面 emit requestClosed(); this->close(); diff --git a/src/lightdm-deepin-greeter/logintipswindow.h b/src/lightdm-deepin-greeter/logintipswindow.h index 53dc0a0f..aa9c9a2b 100644 --- a/src/lightdm-deepin-greeter/logintipswindow.h +++ b/src/lightdm-deepin-greeter/logintipswindow.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef LOGINTIPSWINDOW_H #define LOGINTIPSWINDOW_H diff --git a/src/lightdm-deepin-greeter/loginwindow.cpp b/src/lightdm-deepin-greeter/loginwindow.cpp index 4c12c313..95636acc 100644 --- a/src/lightdm-deepin-greeter/loginwindow.cpp +++ b/src/lightdm-deepin-greeter/loginwindow.cpp @@ -1,89 +1,112 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "loginwindow.h" #include "logincontent.h" #include "userinfo.h" #include +#include +DCORE_USE_NAMESPACE LoginWindow::LoginWindow(SessionBaseModel *const model, QWidget *parent) - : FullscreenBackground(model, parent) - , m_loginContent(new LoginContent(model, this)) + : FullScreenBackground(model, parent) , m_model(model) + , m_dconfig(DConfig::create("org.deepin.dde.daemon", "org.deepin.dde.daemon.account", QString(), this)) { setAccessibleName("LoginWindow"); - updateBackground(m_model->currentUser()->greeterBackground()); - setContent(m_loginContent); - m_loginContent->setVisible(false); + setContent(LoginContent::instance()); - connect(m_loginContent, &LockContent::requestBackground, this, [ = ](const QString & wallpaper) { + connect(LoginContent::instance(), &LockContent::requestBackground, this, [this](const QString & wallpaper) { updateBackground(wallpaper); -#ifdef DISABLE_LOGIN_ANI // 在认证成功以后会通过更改背景来实现登录动画,但是禁用登录动画的情况下,会立即调用startSession, // 导致当前进程被lightdm退掉,X上会残留上一帧的画面,可以看到输入框等画面。使用repaint()强制刷新背景来避免这个问题。 repaint(); -#endif }); - connect(model, &SessionBaseModel::authFinished, this, [ = ](bool successful) { + connect(model, &SessionBaseModel::visibleChanged, this, &LoginWindow::setVisible); + connect(model, &SessionBaseModel::authFinished, this, [this](bool successful) { setEnterEnable(!successful); - if (successful) - m_loginContent->setVisible(false); -#ifdef DISABLE_LOGIN_ANI // 在认证成功以后会通过更改背景来实现登录动画,但是禁用登录动画的情况下,会立即调用startSession, // 导致当前进程被lightdm退掉,X上会残留上一帧的画面,可以看到输入框等画面。使用repaint()强制刷新背景来避免这个问题。 repaint(); -#endif }); +} - connect(m_loginContent, &LockContent::requestSwitchToUser, this, &LoginWindow::requestSwitchToUser); - connect(m_loginContent, &LockContent::requestSetLayout, this, &LoginWindow::requestSetKeyboardLayout); - - connect(m_loginContent, &LockContent::requestCheckAccount, this, &LoginWindow::requestCheckAccount); - connect(m_loginContent, &LockContent::requestStartAuthentication, this, &LoginWindow::requestStartAuthentication); - connect(m_loginContent, &LockContent::sendTokenToAuth, this, &LoginWindow::sendTokenToAuth); - connect(m_loginContent, &LockContent::requestEndAuthentication, this, &LoginWindow::requestEndAuthentication); - connect(m_loginContent, &LockContent::authFinished, this, &LoginWindow::authFinished); +LoginWindow::~LoginWindow() +{ + // 防止对象析构的时候把多屏共享的content对象也析构了 + if (LoginContent::instance()->parent() == this) { + LoginContent::instance()->setParent(nullptr); + } } void LoginWindow::showEvent(QShowEvent *event) { - FullscreenBackground::showEvent(event); + FullScreenBackground::showEvent(event); //greeter界面显示时,需要调用虚拟键盘 m_model->setHasVirtualKB(true); - m_model->setVisible(true); } void LoginWindow::hideEvent(QHideEvent *event) { - FullscreenBackground::hideEvent(event); + FullScreenBackground::hideEvent(event); //greeter界面隐藏时,需要结束虚拟键盘 m_model->setHasVirtualKB(false); - m_model->setVisible(false); +} + +bool LoginWindow::event(QEvent *event) +{ + if (event->type() == QEvent::KeyRelease) { + auto *keyEvent = dynamic_cast(event); + switch (keyEvent->key()) { + // startdde屏蔽了systemd的待机,由greeter处理待机流程 + case Qt::Key_Sleep: { + m_model->setPowerAction(SessionBaseModel::RequireSuspend); + break; + } + case Qt::Key_PowerOff: { + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PowerMode); + break; + } + // win+p时,触发xrandr -q.用于规避联想机型GT730显卡热插拔问题 + case Qt::Key_P: { + if (!qgetenv("XDG_SESSION_TYPE").contains("wayland")) { + if (qApp->queryKeyboardModifiers().testFlag(Qt::MetaModifier)) { + auto ret = QProcess::execute("xrandr", QStringList() << "-q"); + qCInfo(DDE_SHELL) << "Exec `xrandr -q` ret:" << ret; + } + } + break; + } + case Qt::Key_Escape: { + // TODO for test + qCInfo(DDE_SHELL) << "loginWindow::keyPressEvent set terminal false"; + if (m_dconfig) { + bool allowLocalUnlockTerminal = m_dconfig->value("isAllowLocalUnlockTerminal", false).toBool(); + qCInfo(DDE_SHELL) << "allowLocalUnlockTerminal : "< - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGINWINDOW_H #define LOGINWINDOW_H #include "fullscreenbackground.h" +#include "authcommon.h" #include +#include class LoginContent; class SessionBaseModel; class User; -class LoginWindow : public FullscreenBackground +class LoginWindow : public FullScreenBackground { Q_OBJECT public: explicit LoginWindow(SessionBaseModel *const model, QWidget *parent = nullptr); + ~LoginWindow(); signals: void requestSwitchToUser(std::shared_ptr user); void requestSetKeyboardLayout(std::shared_ptr user, const QString &layout); void requestCreateAuthController(const QString &account); - void requestDestoryAuthController(const QString &account); - void requestStartAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); + void requestDestroyAuthController(const QString &account); + void requestStartAuthentication(const QString &account, const AuthCommon::AuthFlags authType); + void sendTokenToAuth(const QString &account, const AuthCommon::AuthType, const QString &token); void requestEndAuthentication(const QString &account, const int authType); void authFinished(); void requestCheckAccount(const QString &account); @@ -56,10 +38,11 @@ class LoginWindow : public FullscreenBackground protected: void showEvent(QShowEvent *event) override; void hideEvent(QHideEvent *event) override; + bool event(QEvent *event) override; private: - LoginContent *m_loginContent; SessionBaseModel *m_model; + DTK_CORE_NAMESPACE::DConfig *m_dconfig; }; #endif // LOGINWINDOW_H diff --git a/src/lightdm-deepin-greeter/sessionwidget.cpp b/src/lightdm-deepin-greeter/sessionwidget.cpp index 90ea27c9..5acacc06 100644 --- a/src/lightdm-deepin-greeter/sessionwidget.cpp +++ b/src/lightdm-deepin-greeter/sessionwidget.cpp @@ -1,42 +1,20 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "sessionwidget.h" -#include "constants.h" #include "sessionbasemodel.h" +#include "dconfig_helper.h" #include -#include -#include #include #include -#include #include #include #include +#include "dbusconstant.h" + static const int SessionButtonWidth = 160; static const int SessionButtonHeight = 160; static const QString DEFAULT_SESSION_NAME = "deepin"; @@ -69,13 +47,13 @@ const QString session_standard_icon_name(const QString &realName) SessionWidget::SessionWidget(QWidget *parent) : QFrame(parent) , m_currentSessionIndex(0) - , m_frameDataBind(FrameDataBind::Instance()) , m_sessionModel(new QLightDM::SessionsModel(this)) , m_userModel(new QLightDM::UsersModel(this)) - , m_allowSwitchingToWayland(getDConfigValue(getDefaultConfigFileName(), "allowSwitchingToWayland", false).toBool()) + , m_allowSwitchingToWayland(DConfigHelper::instance()->getConfig("allowSwitchingToWayland", false).toBool()) , m_isWaylandExisted(false) , m_warningLabel(new QLabel(this)) - , m_defaultSession(getDConfigValue(getDefaultConfigFileName(),"defaultSession", DEFAULT_SESSION_NAME).toString()) + , m_defaultSession(DConfigHelper::instance()->getConfig("defaultSession", DEFAULT_SESSION_NAME).toString()) + , m_resetSessionIndex(true) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); loadSessionList(); @@ -87,26 +65,15 @@ SessionWidget::SessionWidget(QWidget *parent) m_warningLabel->setAlignment(Qt::AlignCenter); m_warningLabel->hide(); - std::function function = std::bind(&SessionWidget::onOtherPageChanged, this, std::placeholders::_1); - int index = m_frameDataBind->registerFunction("SessionWidget", function); - - connect(this, &SessionWidget::destroyed, this, [ = ] { - m_frameDataBind->unRegisterFunction("SessionWidget", index); - }); - - QTimer::singleShot(0, this, [ = ] { - m_frameDataBind->refreshData("SessionWidget"); - }); - // 判断显卡是否支持wayland if (m_allowSwitchingToWayland) { - QDBusInterface systemDisplayInter("com.deepin.system.Display", "/com/deepin/system/Display", - "com.deepin.system.Display", QDBusConnection::systemBus(), this); + QDBusInterface systemDisplayInter(DSS_DBUS::systemDisplayService, DSS_DBUS::systemDisplayPath, + DSS_DBUS::systemDisplayService, QDBusConnection::systemBus(), this); QDBusReply reply = systemDisplayInter.call("SupportWayland"); if (QDBusError::NoError == reply.error().type()) m_allowSwitchingToWayland = reply.value(); else - qWarning() << "Get support wayland property failed: " << reply.error().message(); + qCWarning(DDE_SHELL) << "Get support wayland property failed: " << reply.error().message(); } } @@ -129,11 +96,14 @@ void SessionWidget::updateLayout() { const int itemPadding = 20; const int itemWidth = m_sessionBtns.first()->width(); + const int itemHeight = m_sessionBtns.first()->height(); const int itemTotal = itemPadding + itemWidth; // checked default session button - m_currentSessionIndex = sessionIndex(m_model->sessionKey()); + if (m_resetSessionIndex) + m_currentSessionIndex = sessionIndex(m_model->sessionKey()); m_sessionBtns.at(m_currentSessionIndex)->setChecked(true); + m_resetSessionIndex = false; int count = m_sessionBtns.size(); if (m_isWaylandExisted && !m_allowSwitchingToWayland) @@ -168,7 +138,7 @@ void SessionWidget::updateLayout() m_warningLabel->setFixedSize(width(), 50); m_warningLabel->hide(); - setFixedHeight(itemWidth * (row + 1) + 50); + setFixedHeight(itemHeight * (row + 1) + 50); } int SessionWidget::sessionCount() const @@ -182,7 +152,7 @@ int SessionWidget::sessionCount() const void SessionWidget::switchToUser(const QString &userName) { - qDebug() << "switch to user" << userName; + qDebug() << "Switch to user" << userName; if (m_currentUser != userName) m_currentUser = userName; @@ -194,9 +164,8 @@ void SessionWidget::switchToUser(const QString &userName) m_currentSessionIndex = sessionIndex(sessionName); m_model->setSessionKey(currentSessionKey()); - m_frameDataBind->updateValue("SessionWidget", m_currentSessionIndex); - qDebug() << userName << "default session is: " << sessionName << m_currentSessionIndex; + qDebug() << "User name: " << userName << ", default session: " << sessionName << ", current session index: " << m_currentSessionIndex; } void SessionWidget::keyPressEvent(QKeyEvent *event) @@ -213,7 +182,7 @@ void SessionWidget::keyPressEvent(QKeyEvent *event) rightKeySwitch(); break; case Qt::Key_Escape: - emit hideFrame(); + hideSessionFrame(); break; default: break; @@ -222,7 +191,7 @@ void SessionWidget::keyPressEvent(QKeyEvent *event) void SessionWidget::mouseReleaseEvent(QMouseEvent *event) { - emit hideFrame(); + hideSessionFrame(); return QFrame::mouseReleaseEvent(event); } @@ -264,7 +233,7 @@ void SessionWidget::onSessionButtonClicked() m_model->setSessionKey(currentSessionKey()); - emit hideFrame(); + hideSessionFrame(); m_warningLabel->hide(); } @@ -283,24 +252,10 @@ int SessionWidget::sessionIndex(const QString &sessionName) } // NOTE: The current session does not exist - qWarning() << "The session does not exist, using the default value."; + qCWarning(DDE_SHELL) << "The session does not exist, using the default value."; return defaultSessionIndex; } -void SessionWidget::onOtherPageChanged(const QVariant &value) -{ - const int index = value.toInt(); - if (index == m_currentSessionIndex) - return; - - for (RoundItemButton *button : m_sessionBtns) { - button->setChecked(false); - } - - m_sessionBtns.at(index)->setChecked(true); - m_currentSessionIndex = index; -} - void SessionWidget::leftKeySwitch() { if (m_currentSessionIndex == 0) { @@ -310,7 +265,6 @@ void SessionWidget::leftKeySwitch() } m_sessionBtns.at(m_currentSessionIndex)->setChecked(true); - m_frameDataBind->updateValue("SessionWidget", m_currentSessionIndex); } void SessionWidget::rightKeySwitch() @@ -322,13 +276,12 @@ void SessionWidget::rightKeySwitch() } m_sessionBtns.at(m_currentSessionIndex)->setChecked(true); - m_frameDataBind->updateValue("SessionWidget", m_currentSessionIndex); } void SessionWidget::chooseSession() { emit m_sessionBtns.at(m_currentSessionIndex)->clicked(); - emit hideFrame(); + hideSessionFrame(); } void SessionWidget::loadSessionList() @@ -342,7 +295,7 @@ void SessionWidget::loadSessionList() const QString hoverIcon = QString(":/img/sessions_icon/%1_hover.svg").arg(session_icon); const QString pressIcon = QString(":/img/sessions_icon/%1_press.svg").arg(session_icon); - qDebug() << "found session: " << session_name << session_icon; + qDebug() << "Load session list, found session, session name: " << session_name << "session icon: " << session_icon; RoundItemButton *sbtn = nullptr; if (session_name == "deepin") { sbtn = new RoundItemButton("X11", this); @@ -384,3 +337,9 @@ void SessionWidget::showEvent(QShowEvent *event) updateLayout(); QWidget::showEvent(event); } + +void SessionWidget::hideSessionFrame() +{ + m_resetSessionIndex = true; + emit notifyHideSessionFrame(); +} diff --git a/src/lightdm-deepin-greeter/sessionwidget.h b/src/lightdm-deepin-greeter/sessionwidget.h index 1265921e..2e5beb16 100644 --- a/src/lightdm-deepin-greeter/sessionwidget.h +++ b/src/lightdm-deepin-greeter/sessionwidget.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef SESSIONWIDGET_H #define SESSIONWIDGET_H @@ -34,7 +13,6 @@ #include #include "rounditembutton.h" -#include "framedatabind.h" class SessionBaseModel; class SessionWidget : public QFrame @@ -53,7 +31,7 @@ class SessionWidget : public QFrame signals: void sessionChanged(const QString &sessionName); - void hideFrame(); + void notifyHideSessionFrame(); public slots: void switchToUser(const QString &userName); @@ -75,14 +53,13 @@ private slots: private: int sessionIndex(const QString &sessionName); - void onOtherPageChanged(const QVariant &value); QString lastLoggedInSession(const QString &userName); + void hideSessionFrame(); private: int m_currentSessionIndex; QString m_currentUser; SessionBaseModel *m_model; - FrameDataBind *m_frameDataBind; QLightDM::SessionsModel *m_sessionModel; QList m_sessionBtns; @@ -91,6 +68,7 @@ private slots: bool m_isWaylandExisted; QLabel *m_warningLabel; QString m_defaultSession; + bool m_resetSessionIndex; }; #endif // SESSIONWIDGET_H diff --git a/src/pam-inhibit-autologin/CMakeLists.txt b/src/pam-inhibit-autologin/CMakeLists.txt new file mode 100644 index 00000000..0c5ccb99 --- /dev/null +++ b/src/pam-inhibit-autologin/CMakeLists.txt @@ -0,0 +1,16 @@ +set(PAM_LIB_NAME "pam_inhibit_autologin") + +file(GLOB_RECURSE LIB_SRCS + "*.h" + "*.c" +) + +add_library(${PAM_LIB_NAME} MODULE + ${LIB_SRCS} +) +set_target_properties(${PAM_LIB_NAME} PROPERTIES PREFIX "") + +target_link_libraries(${PAM_LIB_NAME} PRIVATE + -lpam +) +install(TARGETS ${PAM_LIB_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/security) \ No newline at end of file diff --git a/src/pam-inhibit-autologin/pam_inhibit_autologin.c b/src/pam-inhibit-autologin/pam_inhibit_autologin.c new file mode 100644 index 00000000..e2e7f31d --- /dev/null +++ b/src/pam-inhibit-autologin/pam_inhibit_autologin.c @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2011 - 2025 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include +#include +#include + +// PAM 认证函数 +PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + // pre-greeter.sh脚本用于检查是否存在需要在greeter之前执行的程序,返回0:存在 返回非0:不存在 + const char *shell_path = "/usr/share/dde-session-shell/greeters.d/pre-greeter"; + FILE *file = fopen(shell_path, "r"); + if (file != NULL) { + fclose(file); + int error_code = system(shell_path); + pam_syslog(pamh, LOG_INFO, "run %s return %d", shell_path, error_code); + // 如果脚本没有返回错误,则需要中断自动登录,跳转至greeter + return error_code == 0 ? PAM_PERM_DENIED : PAM_SUCCESS; + } + pam_syslog(pamh, LOG_INFO, "%s not exist, continue auto login ", shell_path); + return PAM_SUCCESS; +} + +// PAM 设置环境函数 +PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { + // 在这里设置凭据(如果需要) + return PAM_SUCCESS; +} \ No newline at end of file diff --git a/src/session-widgets/assist_login_widget.cpp b/src/session-widgets/assist_login_widget.cpp new file mode 100644 index 00000000..bb0a5f7c --- /dev/null +++ b/src/session-widgets/assist_login_widget.cpp @@ -0,0 +1,227 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "assist_login_widget.h" +#include "plugin_manager.h" + +using DSS_PLUGIN_TYPE = dss::module::BaseModuleInterface::ModuleType; + +QList AssistLoginWidget::AssistLoginWidgetObjs = {}; + +AssistLoginWidget::AssistLoginWidget(QWidget *parent) + : AuthModule(AuthCommon::AT_Password, parent) + , m_mainLayout(new QVBoxLayout(this)) + , m_module(nullptr) +{ + m_mainLayout->setContentsMargins(0, 0, 0, 0); + m_mainLayout->setSpacing(0); + + AssistLoginWidgetObjs.append(this); +} + +AssistLoginWidget::~AssistLoginWidget() +{ + if (m_module && m_module->content() && m_module->content()->parent() == this) { + m_module->content()->setParent(nullptr); + } + m_module->reset(); +} + +void AssistLoginWidget::setModule(LoginPlugin *module) +{ + m_module = module; + + setCallback(); + updateVisible(); +} + +void AssistLoginWidget::initUI() +{ + qCInfo(DDE_SHELL) << Q_FUNC_INFO << "AssistLoginWidget initUi"; + if (!m_module) { + return; + } + + if (!m_module->content() || m_module->content()->parent() == nullptr) { + qCInfo(DDE_SHELL) << Q_FUNC_INFO << "m_module->init()"; + m_module->init(); + m_mainLayout->addWidget(m_module->content()); + setFocusProxy(m_module->content()); + } +} + +dss::module::BaseModuleInterface::ModuleType AssistLoginWidget::pluginType() const +{ + if (m_module) + return m_module->type(); + + return dss::module::BaseModuleInterface::ModuleType::LoginType; +} + +void AssistLoginWidget::setCallback() +{ + if (!m_module) { + qCWarning(DDE_SHELL) << "Plugin module is null"; + return; + } + m_module->setMessageCallback(&AssistLoginWidget::messageCallback); + m_module->setAppData(this); + m_module->setAuthCallback(&AssistLoginWidget::authCallback); +} + +void AssistLoginWidget::authCallback(const LoginPlugin::AuthCallbackData *callbackData, void *app_data) +{ + qCInfo(DDE_SHELL) << Q_FUNC_INFO << "AuthCustom::authCallback"; + AssistLoginWidget *assistLoginWidget = getAssistLoginWidgetObj(app_data); + if (callbackData && assistLoginWidget) { + assistLoginWidget->setAuthData(*callbackData); + } +} + +QString AssistLoginWidget::messageCallback(const QString &message, void *app_data) +{ + qCInfo(DDE_SHELL) << "Received message: " << message; + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + + QJsonObject retObj; + QJsonObject dataObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + retObj["Code"] = -1; + retObj["Message"] = "Failed to analysis message info"; + qCWarning(DDE_SHELL) << "Failed to analysis message info from plugin!: " << message; + return toJson(retObj); + } + + QJsonObject messageObj = messageDoc.object(); + AssistLoginWidget *assistLoginWidget = getAssistLoginWidgetObj(app_data); + if (!assistLoginWidget) { + retObj["Code"] = -1; + retObj["Message"] = "App data is nullptr!"; + return toJson(retObj); + } + + QString cmdType = messageObj.value("CmdType").toString(); + qCInfo(DDE_SHELL) << "Cmd type: " << cmdType; + if (cmdType == "GetProperties") { + return PluginManager::instance()->getProperties(messageObj); + } + + if (cmdType == "ReadyToAuthChanged") { + Q_EMIT assistLoginWidget->readyToAuthChanged(messageObj["Data"].toBool()); + } else if (cmdType == "PluginEnabledChanged") { + assistLoginWidget->setVisible(messageObj["Data"].toBool()); + } + + retObj["Data"] = dataObj; + return toJson(retObj); +} + +void AssistLoginWidget::setAuthData(const LoginPlugin::AuthCallbackData &callbackData) +{ + m_currentAuthData = callbackData; + qCDebug(DDE_SHELL) << Q_FUNC_INFO << m_currentAuthData.result; + const QString &account = callbackData.account; + const QString &token = callbackData.token; + if (DSS_PLUGIN_TYPE::PasswordExtendLoginType == pluginType()) { + qCInfo(DDE_SHELL) << "Request send extra info, result: " << callbackData.result; + m_extraInfo = token; + if (dss::module::AuthResult::Success == callbackData.result) + Q_EMIT requestSendExtraInfo(token); + return; + } + + if (dss::module::AuthResult::Success != callbackData.result) { + qCWarning(DDE_SHELL) << "Custom auth result is not success"; + return; + } + + if (!account.isEmpty()) { + qCInfo(DDE_SHELL) << Q_FUNC_INFO << "requestSendToken: " << account << token; + emit requestSendToken(account, token); + } +} + +void AssistLoginWidget::updateConfig() +{ + if (!m_module) { + return; + } + + m_module->updateConfig(); + setPluginConfig(m_module->pluginConfig()); +} + +AssistLoginWidget *AssistLoginWidget::getAssistLoginWidgetObj(void *app_data) +{ + AssistLoginWidget *assistLoginWidget = static_cast(app_data); + if (AssistLoginWidgetObjs.contains(assistLoginWidget)) { + return assistLoginWidget; + } + + if (AssistLoginWidgetObjs.size() > 0) { + return AssistLoginWidgetObjs.first(); + } + + return nullptr; +} + +QSize AssistLoginWidget::contentSize() const +{ + if (!m_module || !m_module->content()) { + return QSize(); + } + + return m_module->content()->size(); +} + +void AssistLoginWidget::startAuth() +{ + qCDebug(DDE_SHELL) << Q_FUNC_INFO << m_currentAuthData.result; + if (m_currentAuthData.result != 0) { + setAuthData(m_currentAuthData); + } +} + +void AssistLoginWidget::resetAuth() +{ + qCInfo(DDE_SHELL) << Q_FUNC_INFO << "Reset AssistLoginWidget auth"; + m_currentAuthData = LoginPlugin::AuthCallbackData(); +} + +const LoginPlugin::PluginConfig &AssistLoginWidget::getPluginConfig() const +{ + return m_pluginConfig; +} + +void AssistLoginWidget::setPluginConfig(const LoginPlugin::PluginConfig &pluginConfig) +{ + if (m_pluginConfig != pluginConfig) { + m_pluginConfig = pluginConfig; + Q_EMIT requestPluginConfigChanged(m_pluginConfig); + } +} + +void AssistLoginWidget::setAuthState(AuthCommon::AuthState state, const QString &result) +{ + if (m_module) { + m_module->authStateChanged(AuthCommon::AT_Password, state, result); + } +} + +void AssistLoginWidget::updateVisible() +{ + if (m_module) + setVisible(m_module->isPluginEnabled()); +} + +bool AssistLoginWidget::readyToAuth() const +{ + if (m_module) + return m_module->readyToAuth(); + + return true; +} diff --git a/src/session-widgets/assist_login_widget.h b/src/session-widgets/assist_login_widget.h new file mode 100644 index 00000000..c1af183b --- /dev/null +++ b/src/session-widgets/assist_login_widget.h @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ASSIST_LOGIN_WIDGET_H +#define ASSIST_LOGIN_WIDGET_H + +#include +#include "login_module_interface.h" +#include "auth_module.h" +#include "login_plugin.h" + +#include "auth_widget.h" +#include "userinfo.h" + +class AssistLoginWidget: public AuthModule +{ + Q_OBJECT + +public: + explicit AssistLoginWidget(QWidget *parent = nullptr); + ~AssistLoginWidget(); + + void setModule(LoginPlugin *module); + void initUI(); + QSize contentSize() const; + void startAuth(); + void resetAuth(); + void updateConfig(); + void updateVisible(); + + const LoginPlugin::PluginConfig &getPluginConfig() const; + void setPluginConfig(const LoginPlugin::PluginConfig &PluginConfig); + void setAuthState(AuthCommon::AuthState state, const QString &result); + dss::module::BaseModuleInterface::ModuleType pluginType() const; + bool readyToAuth() const; + QString extraInfo() const { return m_extraInfo; } + +Q_SIGNALS: + void requestCheckAccount(const QString &account); + void requestSendToken(const QString &account, const QString &token); + void requestPluginConfigChanged(const LoginPlugin::PluginConfig &PluginConfig); + void requestHidePlugin(); + void readyToAuthChanged(bool ready); + void requestSendExtraInfo(const QString &info); + +private: + void setCallback(); + static void authCallback(const LoginPlugin::AuthCallbackData *callbackData, void *app_data); + static QString messageCallback(const QString &message, void *app_data); + void setAuthData(const LoginPlugin::AuthCallbackData &callbackData); + static AssistLoginWidget *getAssistLoginWidgetObj(void *app_data); + + QVBoxLayout *m_mainLayout; + LoginPlugin::AuthCallbackData m_currentAuthData; + LoginPlugin *m_module; + static QList AssistLoginWidgetObjs; + LoginPlugin::PluginConfig m_pluginConfig; + QString m_extraInfo; +}; + + +#endif //ASSIST_LOGIN_WIDGET_H diff --git a/src/session-widgets/auth_custom.cpp b/src/session-widgets/auth_custom.cpp index 8c46eb60..6f3592f8 100644 --- a/src/session-widgets/auth_custom.cpp +++ b/src/session-widgets/auth_custom.cpp @@ -1,82 +1,443 @@ -/* - * Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_custom.h" #include "modules_loader.h" +#include "sessionbasemodel.h" #include using namespace dss::module; -AuthCustom::AuthCustom(QWidget *parent) - : AuthModule(AuthCommon::AT_Custom, parent) +QList AuthCustom::AuthCustomObjs = {}; + +AuthCustom::AuthCustom(QWidget *parent, AuthCommon::AuthType type) + : AuthModule(type, parent) , m_mainLayout(new QVBoxLayout(this)) - , m_module(nullptr) + , m_plugin(nullptr) + , m_model(nullptr) { - setObjectName(QStringLiteral("AuthCutom")); - setAccessibleName(QStringLiteral("AuthCutom")); + setObjectName(QStringLiteral("AuthCustom")); + setAccessibleName(QStringLiteral("AuthCustom")); m_mainLayout->setContentsMargins(0, 0, 0, 0); m_mainLayout->setSpacing(0); + + AuthCustomObjs.append(this); + + // 需要父类的定时解锁 + AuthModule::initConnections(); } -void AuthCustom::setModule(dss::module::LoginModuleInterface *module) +AuthCustom::~AuthCustom() { - if (m_module) { + detachPlugin(); + // FIXME 这种处理方式不通用,应该由插件请求登陆器把自己卸载掉 + AuthCustomObjs.removeAll(this); +} + +void AuthCustom::detachPlugin() +{ + qCInfo(DDE_SHELL) << "Detach plugin"; + if (m_plugin && m_plugin->content() && m_plugin->content()->parent() == this) { + m_plugin->content()->setParent(nullptr); + } + + m_plugin = nullptr; +} + +void AuthCustom::setModule(LoginPlugin *module) +{ + if (m_plugin) { return; } - m_module = module; + m_plugin = module; - init(); + setCallback(); } -void AuthCustom::init() +void AuthCustom::setModel(const SessionBaseModel *model) { - m_authCallback.app_data = this; - m_authCallback.callbackFun = AuthCustom::authCallBack; - m_module->setAuthFinishedCallback(&m_authCallback); + if (!model || m_model == model) + return; + + m_model = model; + // 通知插件当前用户发生变化 + connect(m_model, &SessionBaseModel::currentUserChanged, this, [this](const std::shared_ptr currentUser) { + if (!currentUser || !m_plugin) + return; - if (m_module->content()->parent() == nullptr) { - m_mainLayout->addWidget(m_module->content()); + m_plugin->notifyCurrentUserChanged(currentUser->name(), currentUser->uid()); + }); +} + +void AuthCustom::setCallback() +{ + if (!m_plugin) { + qCWarning(DDE_SHELL) << "Plugin module is null"; + return; + } + m_plugin->setMessageCallback(&AuthCustom::messageCallback); + m_plugin->setAppData(this); + m_plugin->setAuthCallback(&AuthCustom::authCallback); +} + +void AuthCustom::initUi() +{ + if (!m_plugin) + return; + + if (!m_plugin->content() || m_plugin->content()->parent() == nullptr) { + qCInfo(DDE_SHELL) << "Init module"; + m_plugin->init(); + m_mainLayout->addWidget(m_plugin->content()); + setFocusProxy(m_plugin->content()); } + + updateConfig(); +} + +void AuthCustom::resetAuth() +{ + m_currentAuthData = LoginPlugin::AuthCallbackData(); } -void AuthCustom::setAuthState(const int state, const QString &result) +void AuthCustom::reset() +{ + if (m_plugin) + m_plugin->reset(); +} + +void AuthCustom::setAuthState(const AuthCommon::AuthState state, const QString &result) { - qDebug() << "AuthCustom::setAuthState:" << state << result; m_state = state; switch (state) { + case AuthCommon::AS_Started: + // greeter需要等lightdm开启验证后再发送认证信息 + if (m_model->appType() == AuthCommon::AppType::Lock) { + // FIXME: 并不是所有插件都会有此场景下发token的需求,因此注意清空authdata + sendAuthToken(); + } + break; case AuthCommon::AS_Success: emit authFinished(state); break; + case AuthCommon::AS_Unlocked: + // 切换用户时,会有解锁的动作,因此需要响应unlock + emit activeAuth(m_type); + break; default: break; } } -void AuthCustom::authCallBack(const AuthCallbackData *callbackData, void *app_data) +void AuthCustom::setAuthData(const LoginPlugin::AuthCallbackData &callbackData) +{ + m_currentAuthData = callbackData; + if (LoginPlugin::AuthResult::Success != callbackData.result) { + qCWarning(DDE_SHELL) << "Custom auth result is not success"; + return; + } + + const QString &account = m_currentAuthData.account; + if (!account.isEmpty()) { + qCInfo(DDE_SHELL) << "Request check account: " << account; + emit requestCheckAccount(account, m_plugin->pluginConfig().switchUserWhenCheckAccount); + } else { + // 如果插件的token信息带上了用户名,则通过checkAccount信号通知外面去做用户切换或发送token + // 隐式地要求插件仅在主动切换用户时需要填充token的account,注意需要在代码中增加信号响应,参见sfawidget + Q_EMIT requestSendToken(m_currentAuthData.token); + resetAuth(); + } +} + +void AuthCustom::authCallback(const LoginPlugin::AuthCallbackData *callbackData, void *app_data) +{ + qCInfo(DDE_SHELL) << "Receive auth callback"; + AuthCustom *authCustom = getAuthCustomObj(app_data); + if (callbackData && authCustom) { + authCustom->setAuthData(*callbackData); + } +} + +QString AuthCustom::messageCallback(const QString &message, void *app_data) +{ + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + + QJsonObject retObj; + QJsonObject dataObj; + retObj["Code"] = 0; + retObj["Message"] = "Success"; + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + retObj["Code"] = -1; + retObj["Message"] = "Failed to analysis message info"; + qCWarning(DDE_SHELL) << "Failed to analysis message from plugin: " << message; + return toJson(retObj); + } + + QJsonObject messageObj = messageDoc.object(); + AuthCustom *authCustom = getAuthCustomObj(app_data); + if (!authCustom) { + retObj["Code"] = -1; + retObj["Message"] = "App data is nullptr!"; + return toJson(retObj); + } + + const SessionBaseModel *model = authCustom->getModel(); + if (!model) { + retObj["Code"] = -1; + retObj["Message"] = "Data model is nullptr!"; + return toJson(retObj); + } + + QString cmdType = messageObj.value("CmdType").toString(); + qCInfo(DDE_SHELL) << "Cmd type: " << cmdType; + if (cmdType == "GetProperties") { + QJsonArray properties; + properties = messageObj.value("Data").toArray(); + + if (properties.contains("AppType")) { + dataObj["AppType"] = model->appType(); + } + + if (properties.contains("CurrentUser")) { + if (model->currentUser()) { + QJsonObject user; + user["Name"] = model->currentUser()->name(); + user["Uid"] = static_cast(model->currentUser()->uid()); + dataObj["CurrentUser"] = user; + } else { + retObj["Code"] = -1; + retObj["Message"] = "Current user is null!"; + } + } + } else if (cmdType == "setAuthTypeInfo") { + QJsonObject dataObj = messageObj.value("Data").toObject(); + authCustom->changeAuthType(AUTH_TYPE_CAST(dataObj["AuthType"].toInt())); + } + + retObj["Data"] = dataObj; + return toJson(retObj); +} + +/** + * @brief 将插件回传的void对象指针转换为AuthCustom指针 + * + * 这样做的原因在于,如果存在屏幕插拔的情况,那么AuthCustom *会被释放掉,但是插件是不知道的(也不能依赖插件去做这个处理) + * 后面插件把这个app_data回传到登录器,需要与AuthCustomObjs中保存的指针对比,判断app_data指针是否可用。 + * + * @param app_data 从插件回传的AuthCustom对象指针 + * @return AuthCustom* AuthCustom对象指针 + */ +AuthCustom *AuthCustom::getAuthCustomObj(void *app_data) +{ + AuthCustom *authCustom = static_cast(app_data); + if (AuthCustomObjs.contains(authCustom)) { + return authCustom; + } + + if (AuthCustomObjs.size() > 0) { + return AuthCustomObjs.first(); + } + + return nullptr; +} + +void AuthCustom::changeAuthType(AuthCommon::AuthType type) +{ + // 多个自定义插件时需要匹配当前的类型 + auto tmpType = type; + if (type == AuthCommon::AT_Custom) + tmpType = static_cast(customAuthType()); + + emit notifyAuthTypeChange(tmpType); +} + +LoginPlugin* AuthCustom::getLoginPlugin() const +{ + return m_plugin; +} + +QString AuthCustom::loginPluginKey() const +{ + if (m_plugin) + return m_plugin->key(); + + return QStringLiteral(); +} + +bool AuthCustom::event(QEvent *e) +{ + if(e->type() == QEvent::Resize || e->type() == QEvent::Show) { + emit notifyResizeEvent(); + + if (e->type() == QEvent::Show) { + if (m_plugin && m_plugin->content() && m_plugin->content()->parent() != this) { + m_mainLayout->addWidget(m_plugin->content()); + setFocusProxy(m_plugin->content()); + // 重新设置传给插件的appData + setCallback(); + } + } + } + return AuthModule::event(e); +} + +// 响应解锁 +void AuthCustom::updateUnlockPrompt() +{ + // DA不会主动刷新limit信息,以当前解锁时间判断 + if (m_integerMinutes == 0) { + QTimer::singleShot(1000, this, [this] { + emit activeAuth(m_type); + }); + qCInfo(DDE_SHELL) << "Waiting authentication service..."; + } +} + +void AuthCustom::updateConfig() +{ + if (!m_plugin) + return; + + m_plugin->updateConfig(); +} + +QSize AuthCustom::contentSize() const +{ + if (!m_plugin || !m_plugin->content()) + return QSize(); + + return m_plugin->content()->size(); +} + +QSize AuthCustom::contentSizeHint() const +{ + if (!m_plugin || !m_plugin->content()) + return QSize(); + + return m_plugin->content()->sizeHint(); +} + +LoginPlugin::PluginConfig AuthCustom::pluginConfig() const +{ + if (!m_plugin) + return LoginPlugin::PluginConfig(); + + return m_plugin->pluginConfig(); +} + +void AuthCustom::sendAuthToken() { - qDebug() << "AuthCustom::authCallBack"; - if (callbackData && callbackData->result == 1) { - emit static_cast(app_data)->requestAuthenticate(); + qCInfo(DDE_SHELL) << "Send auth token"; + if (m_currentAuthData.result == LoginPlugin::AuthResult::Success) { + Q_EMIT requestSendToken(m_currentAuthData.token); + } else { + qCWarning(DDE_SHELL) << "Current validation is not successfully"; } + resetAuth(); +} + +void AuthCustom::lightdmAuthStarted() +{ + if (!m_plugin) + return; + + // 在用户A的界面登陆用户B,将结果返回后,首先会进行一次用户切换 + // 切换完成后把之前插件发送的验证结果进行一次验证 + sendAuthToken(); + + // Tell plugin that lightdm authentication started + QJsonObject message; + message["CmdType"] = "StartAuth"; + QJsonObject retDataObj; + retDataObj["AuthObjectType"] = AuthObjectType::LightDM; + message["Data"] = retDataObj; + QString result = m_plugin->message(toJson(message)); + qCInfo(DDE_SHELL) << "Plugin message: " << result; +} + +void AuthCustom::notifyAuthState(AuthCommon::AuthFlags authType, AuthCommon::AuthState state) +{ + qCInfo(DDE_SHELL) << "Notify auth state, auth type: " << authType << ", auth state: " << state; + if (!m_plugin) + return; + + QJsonObject message; + message["CmdType"] = "AuthState"; + QJsonObject retDataObj; + retDataObj["AuthType"] = static_cast(authType); + retDataObj["AuthState"] = state; + message["Data"] = retDataObj; + m_plugin->message(toJson(message)); +} + +/** + * @brief 将限制信息发给插件 + * + * @param limitsInfoStr 插件信息的json数据 + */ +void AuthCustom::setLimitsInfo(const QMap &limitsInfo) +{ + // 把输密码错误五次后,是否锁定的信息传给插件 + if (!m_plugin) + return; + + QJsonArray array; + auto it = limitsInfo.constBegin(); + while (it != limitsInfo.end()) { + array.append(it.value().toJson()); + ++it; + } + QJsonObject message; + message["CmdType"] = "LimitsInfo"; + message["Data"] = array; + m_plugin->message(toJson(message)); +} + +void AuthCustom::setLimitsInfo(const LimitsInfo &limitsInfo) +{ + if (!m_plugin) + return; + + QJsonObject message; + message["CmdType"] = "LimitsInfo"; + + // FIXME: 注意limitsinfo这个结构体没有必要存在两个定义 + QJsonObject obj; + obj["Locked"] = limitsInfo.locked; + obj["MaxTries"] = static_cast(limitsInfo.maxTries); + obj["NumFailures"] = static_cast(limitsInfo.numFailures); + obj["UnlockSecs"] = static_cast(limitsInfo.unlockSecs);; + obj["UnlockTime"] = limitsInfo.unlockTime; + message["Data"] = obj; + m_plugin->message(toJson(message)); + + AuthModule::setLimitsInfo(limitsInfo); +} + +QJsonObject AuthCustom::getRootObj(const QString &jsonStr) +{ + QJsonParseError jsonParseError; + const QJsonDocument &resultDoc = QJsonDocument::fromJson(jsonStr.toLocal8Bit(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || resultDoc.isEmpty()) { + qCWarning(DDE_SHELL) << "Result json parse error: " << jsonParseError.error; + return QJsonObject(); + } + + return resultDoc.object(); +} + +QJsonObject AuthCustom::getDataObj(const QString &jsonStr) +{ + const QJsonObject &rootObj = getRootObj(jsonStr); + if (!rootObj.contains("Data")) { + qCWarning(DDE_SHELL) << "Result doesn't contains the 'data' field"; + return QJsonObject(); + } + + return rootObj["Data"].toObject(); } diff --git a/src/session-widgets/auth_custom.h b/src/session-widgets/auth_custom.h index 5df2b5ac..741f2220 100644 --- a/src/session-widgets/auth_custom.h +++ b/src/session-widgets/auth_custom.h @@ -1,50 +1,87 @@ -/* - * Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHCUTOM_H #define AUTHCUTOM_H #include "auth_module.h" -#include "login_module_interface.h" +#include "authcommon.h" +#include "userinfo.h" +#include "login_plugin.h" #include +#include + +class SessionBaseModel; class AuthCustom : public AuthModule { Q_OBJECT + + enum AuthObjectType { + LightDM, // light display manager - 显示服务器 + DeepinAuthenticate // deepin authentication framework - 深度认证框架 + }; + public: - explicit AuthCustom(QWidget *parent = nullptr); + explicit AuthCustom(QWidget *parent = nullptr, AuthCommon::AuthType type = AuthCommon::AT_Custom); + virtual ~AuthCustom() override; + + void setModule(LoginPlugin *module); + LoginPlugin* getLoginPlugin() const; + QString loginPluginKey() const; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; + LoginPlugin::AuthCallbackData getCurrentAuthData() const { return m_currentAuthData; } + void setModel(const SessionBaseModel *model); + const SessionBaseModel *getModel() const { return m_model; } + void initUi(); + void resetAuth(); + void reset(); + QSize contentSize() const; + QSize contentSizeHint() const; - void setModule(dss::module::LoginModuleInterface *module); + LoginPlugin::PluginConfig pluginConfig() const; + void sendAuthToken(); + void lightdmAuthStarted(); - void setAuthState(const int state, const QString &result) override; + void notifyAuthState(AuthCommon::AuthFlags authType, AuthCommon::AuthState state); + void setLimitsInfo(const LimitsInfo &limitsInfo) override; + void setLimitsInfo(const QMap &limitsInfo); + + void setCustomAuthIndex(int index) { m_customAuthIndex = index; } + int customAuthType() const { return static_cast(AuthCommon::AT_Custom) + m_customAuthIndex; } + + void detachPlugin(); + +protected: + bool event(QEvent *e) override; private: - void init(); - static void authCallBack(const dss::module::AuthCallbackData *callbackData, void *app_data); + void updateUnlockPrompt() override; + void setCallback(); + static void authCallback(const LoginPlugin::AuthCallbackData *callbackData, void *app_data); + static QString messageCallback(const QString &message, void *app_data); + void setAuthData(const LoginPlugin::AuthCallbackData &callbackData); + void updateConfig(); + void changeAuthType(AuthCommon::AuthType type); + static AuthCustom *getAuthCustomObj(void *app_data); + static QJsonObject getDataObj(const QString &jsonStr); + static QJsonObject getRootObj(const QString &jsonStr); + +Q_SIGNALS: + void requestCheckAccount(const QString &account, bool switchUser = true); + void requestSendToken(const QString &token); + void notifyResizeEvent(); + void notifyAuthTypeChange(const AuthCommon::AuthType authType); private: QVBoxLayout *m_mainLayout; - dss::module::AuthCallback m_authCallback; - dss::module::LoginModuleInterface *m_module; + LoginPlugin *m_plugin; + LoginPlugin::AuthCallbackData m_currentAuthData; + const SessionBaseModel *m_model; + static QList AuthCustomObjs; + int m_customAuthIndex; }; #endif // AUTHCUTOM_H diff --git a/src/session-widgets/auth_face.cpp b/src/session-widgets/auth_face.cpp index 479dffb2..30eaf1cd 100644 --- a/src/session-widgets/auth_face.cpp +++ b/src/session-widgets/auth_face.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_face.h" @@ -29,6 +12,7 @@ AuthFace::AuthFace(QWidget *parent) : AuthModule(AuthCommon::AT_Face, parent) , m_aniIndex(-1) , m_textLabel(new DLabel(this)) + , m_filterTimer(new QTimer(this)) { setObjectName(QStringLiteral("AuthFace")); setAccessibleName(QStringLiteral("AuthFace")); @@ -48,12 +32,17 @@ void AuthFace::initUI() /* 文案提示 */ m_textLabel->setText(tr("Face ID")); m_textLabel->setWordWrap(true); - mainLayout->addWidget(m_textLabel, 1, Qt::AlignHCenter); + m_textLabel->setAlignment(Qt::AlignmentFlag::AlignCenter); + mainLayout->addWidget(m_textLabel, 1); /* 认证状态 */ m_authStateLabel = new DLabel(this); m_authStateLabel->installEventFilter(this); setAuthStateStyle(LOGIN_WAIT); mainLayout->addWidget(m_authStateLabel, 0, Qt::AlignRight | Qt::AlignVCenter); + + // 多数摄像头模组前2s内会有由暗变亮的过程,特别是重新上电的第一次,例如待机/休眠/重启等场景,此时获取的人脸图像会报错,此处增加一个定时器,过滤前2s的错误 + m_filterTimer->setInterval(2000); + m_filterTimer->setSingleShot(true); } /** @@ -83,8 +72,9 @@ void AuthFace::reset() * @param state * @param result */ -void AuthFace::setAuthState(const int state, const QString &result) +void AuthFace::setAuthState(const AuthCommon::AuthState state, const QString &result) { + static bool startFilterTimer = false; m_state = state; switch (state) { case AuthCommon::AS_Success: @@ -96,6 +86,7 @@ void AuthFace::setAuthState(const int state, const QString &result) m_showPrompt = true; emit authFinished(state); emit retryButtonVisibleChanged(false); + startFilterTimer = false; break; case AuthCommon::AS_Failure: { setAnimationState(false); @@ -109,6 +100,7 @@ void AuthFace::setAuthState(const int state, const QString &result) } emit retryButtonVisibleChanged(true); emit authFinished(state); + startFilterTimer = false; break; } case AuthCommon::AS_Cancel: @@ -123,9 +115,15 @@ void AuthFace::setAuthState(const int state, const QString &result) m_showPrompt = true; break; case AuthCommon::AS_Verify: + if (!startFilterTimer) { + m_filterTimer->start(); + startFilterTimer = true; + } setAnimationState(false); setAuthStateStyle(isMFA() ? LOGIN_SPINNER : AUTH_LOCK); - m_textLabel->setText(result); + if (!m_filterTimer->isActive()) { + m_textLabel->setText(result); + } break; case AuthCommon::AS_Exception: setAnimationState(false); @@ -138,6 +136,7 @@ void AuthFace::setAuthState(const int state, const QString &result) setAuthStateStyle(isMFA() ? LOGIN_WAIT : AUTH_LOCK); break; case AuthCommon::AS_Started: + startFilterTimer = false; m_textLabel->setText(tr("Verify your Face ID")); break; case AuthCommon::AS_Ended: @@ -165,7 +164,7 @@ void AuthFace::setAuthState(const int state, const QString &result) setAnimationState(false); setAuthStateStyle(isMFA() ? LOGIN_WAIT : AUTH_LOCK); m_textLabel->setText(result); - qWarning() << "Error! The state of Face Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "The state of face auth is wrong, state: " << state << ", result: " << result; break; } update(); @@ -209,7 +208,7 @@ void AuthFace::updateUnlockPrompt() QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } diff --git a/src/session-widgets/auth_face.h b/src/session-widgets/auth_face.h index b959d175..e7400a5d 100644 --- a/src/session-widgets/auth_face.h +++ b/src/session-widgets/auth_face.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHFACE_H #define AUTHFACE_H @@ -35,7 +18,7 @@ class AuthFace : public AuthModule void reset(); public slots: - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setAnimationState(const bool start) override; void setLimitsInfo(const LimitsInfo &info) override; void setAuthFactorType(AuthFactorType authFactorType) override; @@ -55,6 +38,7 @@ public slots: private: int m_aniIndex; DLabel *m_textLabel; + QTimer *m_filterTimer; }; #endif // AUTHFACE_H diff --git a/src/session-widgets/auth_fingerprint.cpp b/src/session-widgets/auth_fingerprint.cpp index 9d7e1ad0..cbc40dd3 100644 --- a/src/session-widgets/auth_fingerprint.cpp +++ b/src/session-widgets/auth_fingerprint.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_fingerprint.h" @@ -76,9 +59,8 @@ void AuthFingerprint::reset() * @param state * @param result */ -void AuthFingerprint::setAuthState(const int state, const QString &result) +void AuthFingerprint::setAuthState(const AuthCommon::AuthState state, const QString &result) { - qDebug() << "AuthFingerprint::setAuthResult:" << state << result; m_state = state; switch (state) { case AuthCommon::AS_Success: @@ -159,7 +141,7 @@ void AuthFingerprint::setAuthState(const int state, const QString &result) setAnimationState(false); setAuthStateStyle(isMFA() ? LOGIN_WAIT : AUTH_LOCK); m_textLabel->setText(result); - qWarning() << "Error! The state of Fingerprint Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "The state of Fingerprint Auth is wrong, state: " << state << ", result: " << result; break; } update(); @@ -211,7 +193,7 @@ void AuthFingerprint::updateUnlockPrompt() QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } diff --git a/src/session-widgets/auth_fingerprint.h b/src/session-widgets/auth_fingerprint.h index c1377215..36dbfc3f 100644 --- a/src/session-widgets/auth_fingerprint.h +++ b/src/session-widgets/auth_fingerprint.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHFINGERPRINT_H #define AUTHFINGERPRINT_H @@ -35,7 +18,7 @@ class AuthFingerprint : public AuthModule void reset(); void setAnimationState(const bool start) override; - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setLimitsInfo(const LimitsInfo &info) override; void setAuthFactorType(AuthFactorType authFactorType) override; void doAnimation() override; diff --git a/src/session-widgets/auth_iris.cpp b/src/session-widgets/auth_iris.cpp index 3e1c6743..fced316e 100644 --- a/src/session-widgets/auth_iris.cpp +++ b/src/session-widgets/auth_iris.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_iris.h" @@ -83,7 +66,7 @@ void AuthIris::reset() * @param state * @param result */ -void AuthIris::setAuthState(const int state, const QString &result) +void AuthIris::setAuthState(const AuthCommon::AuthState state, const QString &result) { m_state = state; switch (state) { @@ -165,7 +148,7 @@ void AuthIris::setAuthState(const int state, const QString &result) setAnimationState(false); setAuthStateStyle(isMFA() ? LOGIN_WAIT : AUTH_LOCK); m_textLabel->setText(result); - qWarning() << "Error! The state of Iris Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "The state of iris auth is wrong, state: " << state << ", result: " << result; break; } update(); @@ -209,7 +192,7 @@ void AuthIris::updateUnlockPrompt() QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } diff --git a/src/session-widgets/auth_iris.h b/src/session-widgets/auth_iris.h index 649ffa70..878f2b15 100644 --- a/src/session-widgets/auth_iris.h +++ b/src/session-widgets/auth_iris.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHIRIS_H #define AUTHIRIS_H @@ -37,7 +20,7 @@ class AuthIris : public AuthModule void setAuthFactorType(AuthFactorType authFactorType) override; public slots: - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setAnimationState(const bool start) override; void setLimitsInfo(const LimitsInfo &info) override; diff --git a/src/session-widgets/auth_module.cpp b/src/session-widgets/auth_module.cpp index 59e3f881..f3ddf618 100644 --- a/src/session-widgets/auth_module.cpp +++ b/src/session-widgets/auth_module.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_module.h" @@ -46,9 +29,9 @@ AuthModule::AuthModule(const AuthCommon::AuthType type, QWidget *parent) , m_limitsInfo(new LimitsInfo()) , m_aniTimer(new QTimer(this)) , m_unlockTimer(new QTimer(this)) - , m_showAuthState(true) , m_isAuthing(false) , m_authFactorType(DDESESSIONCC::SingleAuthFactor) + , m_showAuthState(false) { setMinimumHeight(37); @@ -73,7 +56,7 @@ AuthModule::~AuthModule() void AuthModule::initConnections() { /* 认证解锁时间 */ - connect(m_unlockTimer, &QTimer::timeout, this, [ this ] { + connect(m_unlockTimer, &QTimer::timeout, this, [this] { updateIntegerMinutes(); if (m_integerMinutes == 0) m_unlockTimer->stop(); @@ -99,7 +82,7 @@ void AuthModule::setAnimationState(const bool start) * @param state * @param result */ -void AuthModule::setAuthState(const int state, const QString &result) +void AuthModule::setAuthState(const AuthCommon::AuthState state, const QString &result) { Q_UNUSED(result) @@ -135,15 +118,11 @@ void AuthModule::setLimitsInfo(const LimitsInfo &info) updateUnlockTime(); } -void AuthModule::setShowAuthState(bool showAuthState) -{ - m_showAuthState = showAuthState; -} - void AuthModule::setAuthStatueVisible(bool visible) { - if (m_authStateLabel) + if (m_authStateLabel) { m_authStateLabel->setVisible(visible); + } } /** @@ -151,7 +130,7 @@ void AuthModule::setAuthStatueVisible(bool visible) */ void AuthModule::updateUnlockPrompt() { - qInfo() << m_type << "has" << m_integerMinutes << "minutes left to unlock."; + qCInfo(DDE_SHELL) << "Update unlock prompt, type: " << m_type << ", which has " << m_integerMinutes << " minutes left to unlock."; } /** @@ -174,8 +153,7 @@ void AuthModule::updateUnlockTime() void AuthModule::updateIntegerMinutes() { if (QDateTime::fromString(m_limitsInfo->unlockTime, Qt::ISODateWithMs) > QDateTime::currentDateTime()) { - qreal intervalSeconds = QDateTime::fromString(m_limitsInfo->unlockTime, Qt::ISODateWithMs).toLocalTime().toTime_t() - - QDateTime::currentDateTimeUtc().toTime_t(); + qreal intervalSeconds = QDateTime::fromString(m_limitsInfo->unlockTime, Qt::ISODateWithMs).toLocalTime().toSecsSinceEpoch() - QDateTime::currentDateTimeUtc().toSecsSinceEpoch(); m_integerMinutes = static_cast(qCeil(intervalSeconds / 60)); } else { m_integerMinutes = 0; @@ -205,4 +183,4 @@ void AuthModule::setAuthFactorType(AuthFactorType authFactorType) bool AuthModule::isLocked() const { return m_limitsInfo->locked; -} \ No newline at end of file +} diff --git a/src/session-widgets/auth_module.h b/src/session-widgets/auth_module.h index 8d069c85..f08658a6 100644 --- a/src/session-widgets/auth_module.h +++ b/src/session-widgets/auth_module.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHMODULE_H #define AUTHMODULE_H @@ -41,12 +24,13 @@ #define AUTH_LOCK QStringLiteral(":/misc/images/unlock/unlock_1.svg") #define UnionID_Auth QStringLiteral(":/misc/images/auth/UnionID.svg") #define ResetPassword_Exe_Path QStringLiteral("/usr/lib/dde-control-center/reset-password-dialog") +#define DEEPIN_DEEPINID_DAEMON_PATH QStringLiteral("/usr/lib/deepin-deepinid-daemon/deepin-deepinid-daemon") DWIDGET_USE_NAMESPACE using namespace DDESESSIONCC; struct LimitsInfo { - bool locked; // 认证锁定状态 --- true: 锁定 false: 解锁 + bool locked = false; // 认证锁定状态 --- true: 锁定 false: 解锁 uint maxTries; // 最大重试次数 uint numFailures; // 失败次数,一直累加 uint unlockSecs; // 本次锁定总解锁时间(秒),不会随着时间推移减少 @@ -81,14 +65,13 @@ class AuthModule : public QWidget explicit AuthModule(const AuthCommon::AuthType type, QWidget *parent = nullptr); ~AuthModule() override; - inline int authType() const { return m_type; } - inline int authState() const { return m_state; } + inline AuthCommon::AuthType authType() const { return m_type; } + inline AuthCommon::AuthState authState() const { return m_state; } virtual void setAnimationState(const bool start); - virtual void setAuthState(const int state, const QString &result); + virtual void setAuthState(const AuthCommon::AuthState state, const QString &result); void setAuthStateStyle(const QString &path); virtual void setLimitsInfo(const LimitsInfo &info); - void setShowAuthState(bool showAuthState); void setAuthStatueVisible(bool visible); void setAuthStateLabel(DLabel *label); virtual void setAuthFactorType(AuthFactorType authFactorType); @@ -96,8 +79,8 @@ class AuthModule : public QWidget bool isLocked() const; signals: - void activeAuth(const int); - void authFinished(const int); + void activeAuth(const AuthCommon::AuthType); + void authFinished(const AuthCommon::AuthState); void requestAuthenticate(); void unlockTimeChanged(); @@ -110,17 +93,17 @@ class AuthModule : public QWidget protected: int m_inputType; // 认证信息输入设备类型 - int m_state; // 认证状态 - int m_type; // 认证类型 + AuthCommon::AuthState m_state; // 认证状态 + AuthCommon::AuthType m_type; // 认证类型 bool m_showPrompt; // 是否显示默认提示文案 uint m_integerMinutes; // 认证剩余解锁的整数分钟 LimitsInfo *m_limitsInfo; // 认证限制相关信息 QPointer m_authStateLabel; // 认证状态图标 QTimer *m_aniTimer; // 动画执行定时器 QTimer *m_unlockTimer; // 认证解锁定时器 - bool m_showAuthState; // 是否显示认证状态 bool m_isAuthing; // 是否正在验证 AuthFactorType m_authFactorType; // 验证因子类型 + bool m_showAuthState; // 是否显示验证状态控件 }; #endif // AUTHMODULE_H diff --git a/src/session-widgets/auth_passkey.cpp b/src/session-widgets/auth_passkey.cpp new file mode 100644 index 00000000..d262df13 --- /dev/null +++ b/src/session-widgets/auth_passkey.cpp @@ -0,0 +1,256 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "auth_passkey.h" +#include "authcommon.h" + +#include +#include +#include + +AuthPasskey::AuthPasskey(QWidget *parent) + : AuthModule(AuthCommon::AT_Passkey, parent) + , m_aniIndex(-1) + , m_textLabel(new DLabel(this)) + , m_spinner(new DSpinner(this)) + , m_stretchLayout(new QHBoxLayout()) +{ + setObjectName(QStringLiteral("AuthPasskey")); + setAccessibleName(QStringLiteral("AuthPasskey")); + + initUI(); + initConnections(); +} + +/** + * @brief 初始化界面 + */ +void AuthPasskey::initUI() +{ + QHBoxLayout *mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(27, 0, 10, 0); + mainLayout->setSpacing(0); + + /* 旋转提示 */ + m_spinner->setFixedSize(18, 18); + + /* 文案提示 */ + m_textLabel->setText(tr("Please plug in the security key")); + m_textLabel->setWordWrap(true); + + /* 旋转提示和文案提示布局 */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_stretchLayout->setContentsMargins(0, 0, 0, 0); +#else + m_stretchLayout->setMargin(0); +#endif + m_stretchLayout->setSpacing(10); + m_stretchLayout->addStretch(1); + m_stretchLayout->addWidget(m_spinner, 0); + m_stretchLayout->addWidget(m_textLabel, 0); + m_stretchLayout->addStretch(1); + + mainLayout->addLayout(m_stretchLayout, 1); + + /* 认证状态 */ + m_authStateLabel = new DLabel(this); + setAuthStateStyle(LOGIN_WAIT); + mainLayout->addWidget(m_authStateLabel, 0, Qt::AlignRight | Qt::AlignVCenter); + + needSpinner(false); + emit retryButtonVisibleChanged(false); +} + +/** + * @brief 初始化信号连接 + */ +void AuthPasskey::initConnections() +{ + AuthModule::initConnections(); +} + +/** + * @brief AuthPasskey::reset + */ +void AuthPasskey::reset() +{ + m_state = AuthCommon::AS_Ended; + needSpinner(false); + m_textLabel->setText(tr("Please plug in the security key")); +} + +/** + * @brief 设置认证状态 + * + * @param state + * @param result + */ +void AuthPasskey::setAuthState(const AuthCommon::AuthState state, const QString &result) +{ + m_state = state; + switch (state) { + case AuthCommon::AS_Success: + needSpinner(false); + setAnimationState(true); + m_showPrompt = true; + m_textLabel->setText(tr("Verification successful")); + emit authFinished(state); + emit retryButtonVisibleChanged(false); + break; + case AuthCommon::AS_Failure: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_showPrompt = true; + m_textLabel->setText(tr("Verification failed")); + emit retryButtonVisibleChanged(false); + emit authFinished(state); + break; + case AuthCommon::AS_Cancel: + needSpinner(false); + setAnimationState(false); + m_showPrompt = true; + break; + case AuthCommon::AS_Timeout: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_textLabel->setText(result); + emit retryButtonVisibleChanged(true); + break; + case AuthCommon::AS_Error: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_textLabel->setText(result); + m_showPrompt = true; + break; + case AuthCommon::AS_Verify: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_textLabel->setText(result); + emit retryButtonVisibleChanged(false); + break; + case AuthCommon::AS_Exception: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_textLabel->setText(result); + m_showPrompt = true; + break; + case AuthCommon::AS_Prompt: + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + break; + case AuthCommon::AS_Started: + needSpinner(true); + m_textLabel->setText(tr("Identifying the security key")); + break; + case AuthCommon::AS_Ended: + needSpinner(false); + emit retryButtonVisibleChanged(false); + break; + case AuthCommon::AS_Locked: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_showPrompt = false; + emit retryButtonVisibleChanged(false); + break; + case AuthCommon::AS_Recover: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_showPrompt = true; + break; + case AuthCommon::AS_Unlocked: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_showPrompt = true; + emit activeAuth(AuthCommon::AT_Passkey); + emit retryButtonVisibleChanged(false); + break; + default: + needSpinner(false); + setAnimationState(false); + setAuthStateStyle(AUTH_LOCK); + m_textLabel->setText(result); + emit retryButtonVisibleChanged(false); + qCWarning(DDE_SHELL) << "The state of passkey auth is wrong, state: " << state << ", result: " << result; + break; + } + update(); +} + +/** + * @brief 设置认证动画状态 + * + * @param start + */ +void AuthPasskey::setAnimationState(const bool start) +{ + m_aniIndex = 1; + + if (start) { + m_aniTimer->start(20); + } else { + m_aniTimer->stop(); + } +} + +/** + * @brief 更新认证受限信息 + * + * @param info + */ +void AuthPasskey::setLimitsInfo(const LimitsInfo &info) +{ + AuthModule::setLimitsInfo(info); +} + +void AuthPasskey::setAuthFactorType(AuthFactorType authFactorType) +{ + if (DDESESSIONCC::SingleAuthFactor == authFactorType) + layout()->setContentsMargins(10, 0, 10, 0); + + AuthModule::setAuthFactorType(authFactorType); +} + +void AuthPasskey::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + emit activeAuth(m_type); + } + QWidget::mouseReleaseEvent(event); +} + +/** + * @brief 执行动画(认证成功,认证失败,认证中...) + */ +void AuthPasskey::doAnimation() +{ + if (m_state == AuthCommon::AS_Success) { + if (m_aniIndex > 10) { + m_aniTimer->stop(); + emit authFinished(AuthCommon::AS_Success); + } else { + setAuthStateStyle(QStringLiteral(":/misc/images/unlock/unlock_%1.svg").arg(m_aniIndex++)); + } + } +} + +void AuthPasskey::needSpinner(bool need) +{ + if (need) { + m_spinner->setVisible(true); + m_spinner->start(); + m_stretchLayout->setSpacing(10); + } else { + m_spinner->setVisible(false); + m_spinner->stop(); + m_stretchLayout->setSpacing(0); + } +} diff --git a/src/session-widgets/auth_passkey.h b/src/session-widgets/auth_passkey.h new file mode 100644 index 00000000..05fc88c9 --- /dev/null +++ b/src/session-widgets/auth_passkey.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef AUTHPASSKEY_H +#define AUTHPASSKEY_H + +#include "auth_module.h" + +#include + +#include + +DWIDGET_USE_NAMESPACE + +#define Face_Passkey QStringLiteral(":/misc/images/auth/passkey.svg") + +class AuthPasskey : public AuthModule +{ + Q_OBJECT +public: + explicit AuthPasskey(QWidget *parent = nullptr); + + void reset(); + +public slots: + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; + void setAnimationState(const bool start) override; + void setLimitsInfo(const LimitsInfo &info) override; + void setAuthFactorType(AuthFactorType authFactorType) override; + +protected: + void mouseReleaseEvent(QMouseEvent *event) override; + +private: + void initUI(); + void initConnections(); + void doAnimation() override; + void needSpinner(bool need); + +signals: + void retryButtonVisibleChanged(bool visible); + +private: + int m_aniIndex; + DLabel *m_textLabel; + DSpinner *m_spinner; + QHBoxLayout *m_stretchLayout; +}; + +#endif // AUTHPASSKEY_H diff --git a/src/session-widgets/auth_password.cpp b/src/session-widgets/auth_password.cpp index 339e5e25..000fec54 100644 --- a/src/session-widgets/auth_password.cpp +++ b/src/session-widgets/auth_password.cpp @@ -1,63 +1,66 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_password.h" +#include "plugin_manager.h" #include "authcommon.h" #include "dlineeditex.h" +#include "dstyle.h" +#include "dbusconstant.h" #include #include +#include +#include +#include #include #include #include #include #include -#include -#include #include #include #include -#include - -#include +#include +#ifndef ENABLE_DSS_SNIPE +#include #include +#else +#include "userinterface.h" +#endif -#define Service "com.deepin.dialogs.ResetPassword" -#define Path "/com/deepin/dialogs/ResetPassword" -#define Interface "com.deepin.dialogs.ResetPassword" +const QString PASSWORD_HIDE = QStringLiteral(":/misc/images/password-hide.svg"); +const QString PASSWORD_SHOWN = QStringLiteral(":/misc/images/password-shown.svg"); +const QString DConfig_LongPressDisplayPassword = "longPressDisplayPassword"; using namespace AuthCommon; +using DSS_PLUGIN_TYPE = dss::module::BaseModuleInterface::ModuleType; AuthPassword::AuthPassword(QWidget *parent) : AuthModule(AT_Password, parent) , m_capsLock(new DLabel(this)) , m_lineEdit(new DLineEditEx(this)) + , m_passwordShowBtn(new DIconButton(this)) , m_passwordHintBtn(new DIconButton(this)) + , m_passwordTipsWidget(new PasswordErrorTipsWidget(this)) , m_resetPasswordMessageVisible(false) , m_resetPasswordFloatingMessage(nullptr) , m_bindCheckTimer(nullptr) + , m_passwordHintWidget(nullptr) + , m_iconButton(nullptr) + , m_resetDialogShow(false) + , m_isPasswdAuthWidgetReplaced(false) + , m_assistLoginWidget(nullptr) + , m_authenticationDconfig(DConfig::create("org.deepin.dde.authentication", "org.deepin.dde.authentication.errorecho", QString(), this)) + , m_canShowPasswordErrorTips(false) { + qRegisterMetaType("LoginPlugin::PluginConfig"); + + setMaximumSize(500,200); setObjectName(QStringLiteral("AuthPassword")); setAccessibleName(QStringLiteral("AuthPassword")); @@ -65,9 +68,20 @@ AuthPassword::AuthPassword(QWidget *parent) initConnections(); m_lineEdit->installEventFilter(this); + m_lineEdit->setCopyEnabled(false); + m_lineEdit->setCutEnabled(false); setFocusProxy(m_lineEdit); } +AuthPassword::~AuthPassword() +{ + // QWidget析构时会clearFocus, focusChanged会被触发,且槽函数操作了成员变量会导致崩溃,在这里提前断开连接 + m_lineEdit->disconnect(this); + if (m_resetPasswordMessageVisible) { + closeResetPasswordMessage(); + } +} + /** * @brief 初始化界面 */ @@ -75,19 +89,25 @@ void AuthPassword::initUI() { QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->setSpacing(0); + mainLayout->setSpacing(10); m_lineEdit->setClearButtonEnabled(false); m_lineEdit->setEchoMode(QLineEdit::Password); + m_lineEdit->setSecureInputEnabled(true); m_lineEdit->setContextMenuPolicy(Qt::NoContextMenu); m_lineEdit->setFocusPolicy(Qt::StrongFocus); m_lineEdit->lineEdit()->setAlignment(Qt::AlignCenter); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_lineEdit->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression("^[ -~]+$"))); +#else m_lineEdit->lineEdit()->setValidator(new QRegExpValidator(QRegExp("^[ -~]+$"))); +#endif + DFontSizeManager::instance()->bind(m_lineEdit, DFontSizeManager::T6); setLineEditInfo(tr("Password"), PlaceHolderText); QHBoxLayout *passwordLayout = new QHBoxLayout(m_lineEdit->lineEdit()); - passwordLayout->setContentsMargins(5, 0, 10, 0); + passwordLayout->setContentsMargins(10, 0, 10, 0); passwordLayout->setSpacing(5); /* 大小写状态 */ QPixmap pixmap = DHiDPIHelper::loadNxPixmap(CAPS_LOCK); @@ -99,8 +119,21 @@ void AuthPassword::initUI() /* 认证状态 */ m_authStateLabel = new DLabel(this); + m_authStateLabel->setVisible(false); setAuthStateStyle(LOGIN_WAIT); passwordLayout->addWidget(m_authStateLabel, 0, Qt::AlignRight | Qt::AlignVCenter); + + /*显示密码*/ + m_passwordShowBtn->setAccessibleName(QStringLiteral("PasswordShow")); + m_passwordShowBtn->setContentsMargins(0, 0, 0, 0); + m_passwordShowBtn->setFocusPolicy(Qt::NoFocus); + m_passwordShowBtn->setCursor(Qt::ArrowCursor); + m_passwordShowBtn->setFlat(true); + m_passwordShowBtn->setIcon(QIcon(PASSWORD_SHOWN)); + m_passwordShowBtn->setIconSize(QSize(16, 16)); + m_passwordShowBtn->setVisible(true); + passwordLayout->addWidget(m_passwordShowBtn, 0, Qt::AlignRight | Qt::AlignVCenter); + /* 密码提示 */ m_passwordHintBtn->setAccessibleName(QStringLiteral("PasswordHint")); m_passwordHintBtn->setContentsMargins(0, 0, 0, 0); @@ -109,9 +142,34 @@ void AuthPassword::initUI() m_passwordHintBtn->setFlat(true); m_passwordHintBtn->setIcon(QIcon(PASSWORD_HINT)); m_passwordHintBtn->setIconSize(QSize(16, 16)); + m_passwordHintBtn->setVisible(false); passwordLayout->addWidget(m_passwordHintBtn, 0, Qt::AlignRight | Qt::AlignVCenter); - mainLayout->addWidget(m_lineEdit); + auto plugin = PluginManager::instance()->getAssistloginPlugin(); + + if (plugin) { + m_isPasswdAuthWidgetReplaced = true; + m_assistLoginWidget = new AssistLoginWidget(this); + m_assistLoginWidget->setModule(plugin); + m_assistLoginWidget->initUI(); + mainLayout->addWidget(m_assistLoginWidget); + m_lineEdit->hide(); + } else { + m_lineEdit->show(); + } + + // 密码框下面增加一个认证界面 + auto extendPlugin = PluginManager::instance()->getFirstLoginPlugin(dss::module::BaseModuleInterface::PasswordExtendLoginType); + if (extendPlugin) { + m_assistLoginWidget = new AssistLoginWidget(this); + m_assistLoginWidget->setModule(extendPlugin); + m_assistLoginWidget->initUI(); + mainLayout->addWidget(m_assistLoginWidget); + } else { + qCDebug(DDE_SHELL) << "There's no password extend plugin"; + } + updatePasswordTextMargins(); + m_passwordTipsWidget->hide(); } /** @@ -120,23 +178,140 @@ void AuthPassword::initUI() void AuthPassword::initConnections() { AuthModule::initConnections(); + + auto blockEditSig = [this]() -> bool { + return m_assistLoginWidget + && m_assistLoginWidget->isVisible() + && DSS_PLUGIN_TYPE::PasswordExtendLoginType == m_assistLoginWidget->pluginType() + && !m_assistLoginWidget->readyToAuth(); + }; /* 密码提示 */ connect(m_passwordHintBtn, &DIconButton::clicked, this, &AuthPassword::showPasswordHint); /* 密码输入框 */ - connect(m_lineEdit, &DLineEditEx::focusChanged, this, [this](const bool focus) { - if (!focus) m_lineEdit->setAlert(false); + connect(m_lineEdit, &DLineEditEx::focusChanged, this, [this, blockEditSig](const bool focus) { + if (!focus) + m_lineEdit->setAlert(false); m_authStateLabel->setVisible(!focus && m_showAuthState); + updatePasswordTextMargins(); emit focusChanged(focus); + if (focus && !blockEditSig()) { + emit lineEditTextChanged(m_lineEdit->text()); + } + + if (focus) { + QString kbLayout = getCurrentKBLayout(); + if (!kbLayout.isEmpty() && !kbLayout.toLower().startsWith("us")) { + m_originalKBLayout = kbLayout; + qCInfo(DDE_SHELL) << "Original keyboard layout:" << m_originalKBLayout; + // 如果键盘布局有特殊设置,则切换到英文键盘布局,认证成功后恢复 + setKBLayout("us"); + } + } else { + if (!m_originalKBLayout.isEmpty()) { + // 切换回原来的键盘布局 + setKBLayout(m_originalKBLayout); + m_originalKBLayout.clear(); + } + } + }); + + connect(this, &AuthPassword::authFinished, this, [this](const AuthState state) { + if (state == AS_Success) { + if (!m_originalKBLayout.isEmpty()) { + // 切换回原来的键盘布局 + setKBLayout(m_originalKBLayout); + m_originalKBLayout.clear(); + } + } }); - connect(m_lineEdit, &DLineEditEx::textChanged, this, [this](const QString &text) { + + connect(m_lineEdit, &DLineEditEx::textChanged, this, [this, blockEditSig](const QString &text) { m_lineEdit->hideAlertMessage(); + hidePasswordHintWidget(); m_lineEdit->setAlert(false); - emit lineEditTextChanged(text); + updatePasswordTextMargins(); + if (canShowPasswrodErrorTip() && isShowPasswrodErrorTip()) { + m_passwordTipsWidget->reset(); + m_passwordTipsWidget->setErrDetailVisible(false); + m_passwordTipsWidget->setVisible(false); + m_passwordTipsWidget->adjustSize(); + emit passwordErrorTipsClearChanged(true); + } + if (!blockEditSig()) + emit lineEditTextChanged(text); }); - connect(m_lineEdit, &DLineEditEx::returnPressed, this, [ this ] { - if (!m_lineEdit->lineEdit()->isReadOnly()) // 避免用户在验证的时候反复点击 - emit requestAuthenticate(); + connect(m_lineEdit, &DLineEditEx::returnPressed, this, [this, blockEditSig] { + if (!m_lineEdit->lineEdit()->isReadOnly()) { // 避免用户在验证的时候反复点击 + if (!blockEditSig()) { + emit requestAuthenticate(); + } else { + setFocusProxy(m_assistLoginWidget); + m_assistLoginWidget->setFocus(); + } + } }); + + if (DConfigHelper::instance()->getConfig(DConfig_LongPressDisplayPassword, true).toBool()) { + connect(m_passwordShowBtn, &DSuggestButton::pressed, this, [this] { + m_passwordShowBtn->setIcon(QIcon(PASSWORD_HIDE)); + if (m_lineEdit) { + m_lineEdit->setEchoMode(QLineEdit::Normal); + } + }); + + connect(m_passwordShowBtn, &DSuggestButton::released, this, [this] { + m_passwordShowBtn->setIcon(QIcon(PASSWORD_SHOWN)); + if (m_lineEdit) { + m_lineEdit->setEchoMode(QLineEdit::Password); + } + }); + } else { + connect(m_passwordShowBtn, &DSuggestButton::clicked, this, [this] { + if (m_lineEdit->echoMode() == QLineEdit::EchoMode::Password) { + m_passwordShowBtn->setIcon(QIcon(PASSWORD_HIDE)); + m_lineEdit->lineEdit()->setEchoMode(QLineEdit::Normal); + updatePasswordTextMargins(); + } else { + m_passwordShowBtn->setIcon(QIcon(PASSWORD_SHOWN)); + m_lineEdit->lineEdit()->setEchoMode(QLineEdit::Password); + updatePasswordTextMargins(); + } + }); + } + + if (m_assistLoginWidget && m_isPasswdAuthWidgetReplaced) { + connect(m_assistLoginWidget, &AssistLoginWidget::requestPluginConfigChanged, this, [this](const LoginPlugin::PluginConfig pluginConfig) { + Q_EMIT requestPluginConfigChanged(pluginConfig); + }); + connect(m_assistLoginWidget, &AssistLoginWidget::requestHidePlugin, this, [=] { + hidePlugin(); + }); + connect(m_assistLoginWidget, &AssistLoginWidget::requestSendToken, this, &AuthPassword::requestPluginAuthToken); + } + + if (m_assistLoginWidget) { + connect(m_assistLoginWidget, &AssistLoginWidget::requestSendExtraInfo, this, [this](const QString &info) { + if (!m_lineEdit->text().isEmpty()) { + Q_EMIT requestAuthenticate(); + return; + } + + // 焦点切换到密码输入框 + m_lineEdit->setFocus(); + setFocusProxy(m_lineEdit); + }); + connect(m_assistLoginWidget, &AssistLoginWidget::readyToAuthChanged, this, &AuthPassword::onReadyToAuthChanged); + } + + if (m_authenticationDconfig) { + auto updateCanShow = [this] { + m_canShowPasswordErrorTips = m_authenticationDconfig->value("PasswordErrorEcho", false).toBool(); + }; + + connect(m_authenticationDconfig, &DConfig::valueChanged, this, updateCanShow); + + updateCanShow(); + } } /** @@ -144,11 +319,22 @@ void AuthPassword::initConnections() */ void AuthPassword::reset() { - m_lineEdit->clear(); + m_lineEdit->setText(QString()); m_lineEdit->setAlert(false); m_lineEdit->hideAlertMessage(); + setFocusProxy(m_lineEdit); + m_lineEdit->setEchoMode(QLineEdit::Password); + m_passwordShowBtn->setIcon(QIcon(PASSWORD_SHOWN)); + hidePasswordHintWidget(); setLineEditEnabled(true); setLineEditInfo(tr("Password"), PlaceHolderText); + if (m_passwordTipsWidget && canShowPasswrodErrorTip()) { + m_passwordTipsWidget->reset(); + m_passwordTipsWidget->setErrDetailVisible(false); + m_passwordTipsWidget->setVisible(false); + m_passwordTipsWidget->adjustSize(); + emit passwordErrorTipsClearChanged(true); + } } /** @@ -157,27 +343,34 @@ void AuthPassword::reset() * @param state * @param result */ -void AuthPassword::setAuthState(const int state, const QString &result) +void AuthPassword::setAuthState(const AuthState state, const QString &result) { - qDebug() << "AuthPassword::setAuthResult:" << state << result << m_currentUid; m_state = state; switch (state) { case AS_Success: setAnimationState(false); setAuthStateStyle(LOGIN_CHECK); m_lineEdit->setAlert(false); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); setLineEditEnabled(false); setLineEditInfo(tr("Verification successful"), PlaceHolderText); m_showPrompt = true; m_lineEdit->hideAlertMessage(); + hidePasswordHintWidget(); + m_resetDialogShow = false; emit authFinished(state); emit requestChangeFocus(); + if (m_assistLoginWidget) { + m_assistLoginWidget->resetAuth(); + if (isPasswdAuthWidgetReplaced()) { + hidePlugin(); + } + } break; case AS_Failure: { setAnimationState(false); setAuthStateStyle(LOGIN_WAIT); - m_lineEdit->clear(); + m_lineEdit->lineEdit()->selectAll(); setLineEditEnabled(true); const int leftTimes = static_cast(m_limitsInfo->maxTries - m_limitsInfo->numFailures); if (leftTimes > 1) { @@ -185,9 +378,18 @@ void AuthPassword::setAuthState(const int state, const QString &result) } else if (leftTimes == 1) { setLineEditInfo(tr("Verification failed, only one chance left"), PlaceHolderText); } - setLineEditInfo(tr("Wrong Password"), AlertText); + if (canShowPasswrodErrorTip()) { + showErrorTip(tr("Wrong Password")); + } else if (!m_limitsInfo->locked) { + setLineEditInfo(tr("Wrong Password"), AlertText); + } + m_showPrompt = false; emit authFinished(state); + + if (isPasswdAuthWidgetReplaced()) { + hidePlugin(); + } break; } case AS_Cancel: @@ -225,7 +427,6 @@ void AuthPassword::setAuthState(const int state, const QString &result) case AS_Started: break; case AS_Ended: - m_lineEdit->clear(); break; case AS_Locked: setAnimationState(false); @@ -250,14 +451,22 @@ void AuthPassword::setAuthState(const int state, const QString &result) setLineEditEnabled(true); m_showPrompt = true; break; + case AS_VerifyCode: + setAnimationState(false); + setAuthStateStyle(LOGIN_WAIT); + setLineEditEnabled(true); + break; default: setAnimationState(false); setAuthStateStyle(LOGIN_WAIT); setLineEditEnabled(true); setLineEditInfo(result, AlertText); - qWarning() << "Error! The state of Password Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "Error! The state of Password Auth is wrong, state: " << state << ", result: " << result; break; } + if (m_assistLoginWidget) { + m_assistLoginWidget->setAuthState(state, result); + } update(); } @@ -279,6 +488,7 @@ void AuthPassword::setAnimationState(const bool start) void AuthPassword::setCapsLockVisible(const bool on) { m_capsLock->setVisible(on); + updatePasswordTextMargins(); } /** @@ -288,7 +498,6 @@ void AuthPassword::setCapsLockVisible(const bool on) */ void AuthPassword::setLimitsInfo(const LimitsInfo &info) { - qDebug() << "AuthPassword::setLimitsInfo" << info.numFailures; const bool lockStateChanged = (info.locked != m_limitsInfo->locked); AuthModule::setLimitsInfo(info); // 如果lock状态发生变化且当前状态为非lock更新编辑框文案 @@ -296,10 +505,14 @@ void AuthPassword::setLimitsInfo(const LimitsInfo &info) updateUnlockPrompt(); m_passwordHintBtn->setVisible(info.numFailures > 0 && !m_passwordHint.isEmpty()); - if (m_limitsInfo->locked) { - setAuthState(AS_Locked, "Locked"); - if (this->isVisible() && QFile::exists(ResetPassword_Exe_Path) && m_currentUid <= 9999) { - qDebug() << "begin reset passoword"; + updatePasswordTextMargins(); + if (m_limitsInfo->numFailures >= 3) { + if (m_limitsInfo->locked) { + setAuthState(AS_Locked, "Locked"); + } + + if (this->isVisible() && isShowResetPasswordMessage()) { + qCDebug(DDE_SHELL) << "Begin reset passoword"; setResetPasswordMessageVisible(true); updateResetPasswordUI(); } @@ -307,6 +520,9 @@ void AuthPassword::setLimitsInfo(const LimitsInfo &info) setResetPasswordMessageVisible(false); updateResetPasswordUI(); } + + if (lockStateChanged) + emit notifyLockedStateChanged(m_limitsInfo->locked); } /** @@ -319,8 +535,14 @@ void AuthPassword::setLineEditInfo(const QString &text, const TextType type) { switch (type) { case AlertText: - m_lineEdit->showAlertMessage(text, this, 5000); + showAlertMessage(text); m_lineEdit->setAlert(true); + if (canShowPasswrodErrorTip()) { + m_passwordTipsWidget->addErrorDetailMsg(text); + } else { + m_lineEdit->showAlertMessage(text, this, 5000); + m_lineEdit->setAlert(true); + } break; case InputText: { const int cursorPos = m_lineEdit->lineEdit()->cursorPosition(); @@ -368,17 +590,30 @@ QString AuthPassword::lineEditText() const */ void AuthPassword::setLineEditEnabled(const bool enable) { - if (enable && !m_limitsInfo->locked) { + if (!m_passwordLineEditEnabled) { + m_lineEdit->setFocusPolicy(Qt::NoFocus); + m_lineEdit->clearFocus(); + m_lineEdit->lineEdit()->setReadOnly(true); + m_lineEdit->lineEdit()->setEnabled(false); + } else if (enable && !m_limitsInfo->locked) { m_lineEdit->setFocusPolicy(Qt::StrongFocus); m_lineEdit->setFocus(); m_lineEdit->lineEdit()->setReadOnly(false); + m_lineEdit->lineEdit()->setEnabled(true); } else { m_lineEdit->setFocusPolicy(Qt::NoFocus); m_lineEdit->clearFocus(); m_lineEdit->lineEdit()->setReadOnly(true); + m_lineEdit->lineEdit()->setEnabled(true); } } +void AuthPassword::setPasswordLineEditEnabled(const bool enable) +{ + m_passwordLineEditEnabled = enable; + setLineEditEnabled(enable); +} + /** * @brief 更新认证锁定时的文案 */ @@ -386,14 +621,17 @@ void AuthPassword::updateUnlockPrompt() { AuthModule::updateUnlockPrompt(); if (m_integerMinutes == 1) { + m_lineEdit->setText(QString()); m_lineEdit->setPlaceholderText(tr("Please try again 1 minute later")); } else if (m_integerMinutes > 1) { + m_lineEdit->setText(QString()); m_lineEdit->setPlaceholderText(tr("Please try again %n minutes later", "", static_cast(m_integerMinutes))); } else { + setLineEditInfo(tr("Password"), PlaceHolderText); QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } @@ -403,7 +641,19 @@ void AuthPassword::updateUnlockPrompt() */ void AuthPassword::showPasswordHint() { - m_lineEdit->showAlertMessage(m_passwordHint, this, 5000); + // FIXME dtk如果后期提供接口设置alert的调色板,那么直接设置即可 + // 在这里将调色板的TextWarning改成黑色,让DAlertControl继承父类调色板,从而能显示黑色的文字 + DPalette palette = DPaletteHelper::instance()->palette(this->topLevelWidget()); + palette.setColor(DPalette::TextWarning, Qt::black); + DPaletteHelper::instance()->setPalette(this->topLevelWidget(), palette); + + // 每次显示都需要重新生成对象,因为无法修改其内部私有对象的调色板,只能在创建对象的时候从父对象继承 + if (!m_passwordHintWidget) { + m_passwordHintWidget = new DAlertControl(m_lineEdit->lineEdit()); + QTimer::singleShot(5000, this, &AuthPassword::hidePasswordHintWidget); + } + m_passwordHintWidget->showAlertMessage(m_passwordHint, m_lineEdit->lineEdit(), 5000); + m_lineEdit->hideAlertMessage(); } /** @@ -413,22 +663,30 @@ void AuthPassword::showPasswordHint() void AuthPassword::setPasswordHintBtnVisible(const bool isVisible) { m_passwordHintBtn->setVisible(isVisible); + updatePasswordTextMargins(); } /** * @brief 设置重置密码消息框的显示状态数据 - * - * @param visible + * @param isVisible + * @param fromResetDialog 是否通过重置对话框关闭 */ -void AuthPassword::setResetPasswordMessageVisible(const bool isVisible) +void AuthPassword::setResetPasswordMessageVisible(const bool isVisible, bool fromResetDialog) { - qDebug() << "set reset password message visible: " << isVisible; + qCDebug(DDE_SHELL) << "Set reset password message visible, incoming visible:" << isVisible + << " current visible:" << m_resetPasswordMessageVisible + << " fromResetDialog " << fromResetDialog; + if (isVisible && fromResetDialog) { + m_resetDialogShow = false; + } + if (m_resetPasswordMessageVisible == isVisible) return; - // 如果设置为显示重置按钮,但是实际上并没有锁定,直接退出,是是否锁定为准 - if (isVisible && !isLocked()) + // 如果设置为显示重置按钮,失败次数>=3次就显示重置密码 1060-24505 + if (isVisible && ((m_limitsInfo && m_limitsInfo->numFailures < 3) || m_resetDialogShow)) { return; + } m_resetPasswordMessageVisible = isVisible; emit resetPasswordMessageVisibleChanged(m_resetPasswordMessageVisible); @@ -455,33 +713,56 @@ void AuthPassword::showResetPasswordMessage() } QPalette pa; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + pa.setColor(QPalette::Window, QColor(247, 247, 247, 51)); +#else pa.setColor(QPalette::Background, QColor(247, 247, 247, 51)); +#endif + pa.setColor(QPalette::Highlight, Qt::white); + pa.setColor(QPalette::HighlightedText, Qt::black); m_resetPasswordFloatingMessage = new DFloatingMessage(DFloatingMessage::MessageType::ResidentType); m_resetPasswordFloatingMessage->setPalette(pa); - m_resetPasswordFloatingMessage->setIcon(QIcon::fromTheme("dialog-warning")); + // DFloatingMessage 中未放开seticonsize接口,无法设置图标大小,使用缩放函数会造成图标锯齿 + // 只能使用findChildren找到对应的图标控件来设置图标大小进行规避 + // DFloatingMessage中有两个按钮一个是DIconButton,另一个是继承于DIconButton的DDialogCloseButton,需要区分 + QList btnList = m_resetPasswordFloatingMessage->findChildren(); + foreach (const auto iconButton, btnList) { + DDialogCloseButton *closeButton = qobject_cast(iconButton); + if (closeButton) { + continue; + } + iconButton->installEventFilter(this); + m_iconButton = iconButton; + } + m_resetPasswordFloatingMessage->setIcon(QIcon("://misc/images/dss_warning.svg")); DSuggestButton *suggestButton = new DSuggestButton(tr("Reset Password")); + suggestButton->setAutoDefault(true); m_resetPasswordFloatingMessage->setWidget(suggestButton); m_resetPasswordFloatingMessage->setMessage(tr("Forgot password?")); - connect(suggestButton, &QPushButton::clicked, this, [ this ] { - if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(false)) { - qDebug() << "setKeyboardGrabEnabled(false) success!"; - } - const QString AccountsService("com.deepin.daemon.Accounts"); - const QString path = QString("/com/deepin/daemon/Accounts/User%1").arg(m_currentUid); - com::deepin::daemon::accounts::User user(AccountsService, path, QDBusConnection::systemBus()); + connect(suggestButton, &QPushButton::clicked, this, [this] { +#ifndef ENABLE_DSS_SNIPE + com::deepin::daemon::accounts::User +#else + org::deepin::dde::accounts1::User +#endif + user(DSS_DBUS::accountsService, QString(DSS_DBUS::accountsUserPath).arg(m_currentUid), QDBusConnection::systemBus()); auto reply = user.SetPassword(""); + m_resetDialogShow = true; reply.waitForFinished(); if (reply.isError()) - qWarning() << "reply setpassword:" << reply.error().message(); + qCWarning(DDE_SHELL) << "Reset password message error: " << reply.error().message(); emit m_resetPasswordFloatingMessage->closeButtonClicked(); }); - connect(m_resetPasswordFloatingMessage, &DFloatingMessage::closeButtonClicked, this, [this](){ + connect(m_resetPasswordFloatingMessage, &DFloatingMessage::closeButtonClicked, this, [this]() { if (m_resetPasswordFloatingMessage) { - delete m_resetPasswordFloatingMessage; + m_resetPasswordFloatingMessage->deleteLater(); m_resetPasswordFloatingMessage = nullptr; } + m_resetPasswordMessageVisible = false; emit resetPasswordMessageVisibleChanged(false); + // 重置密码后,输入框重新获取焦点 + m_lineEdit->setFocus(); }); DMessageManager::instance()->sendMessage(centerFrame, m_resetPasswordFloatingMessage); } @@ -493,7 +774,7 @@ void AuthPassword::closeResetPasswordMessage() { if (m_resetPasswordFloatingMessage) { m_resetPasswordFloatingMessage->close(); - delete m_resetPasswordFloatingMessage; + m_resetPasswordFloatingMessage->deleteLater(); m_resetPasswordFloatingMessage = nullptr; } } @@ -512,16 +793,16 @@ bool AuthPassword::isUserAccountBinded() return false; } QString uosid; - if (retUOSID.error().message().isEmpty()) { + if (retUOSID.isValid()) { uosid = retUOSID.value(); } else { - qWarning() << retUOSID.error().message(); + qCWarning(DDE_SHELL) << "UOS ID is invalid, error: " << retUOSID.error().message(); return false; } - QDBusInterface accountsInter("com.deepin.daemon.Accounts", - QString("/com/deepin/daemon/Accounts/User%1").arg(m_currentUid), - "com.deepin.daemon.Accounts.User", + QDBusInterface accountsInter(DSS_DBUS::accountsService, + QString(DSS_DBUS::accountsUserPath).arg(m_currentUid), + DSS_DBUS::accountsUserInterface, QDBusConnection::systemBus()); QVariant retUUID = accountsInter.property("UUID"); if (!accountsInter.isValid()) { @@ -529,25 +810,25 @@ bool AuthPassword::isUserAccountBinded() } QString uuid = retUUID.toString(); - QDBusReply retLocalBindCheck= syncHelperInter.call("LocalBindCheck", uosid, uuid); + QDBusReply retLocalBindCheck = syncHelperInter.call("LocalBindCheck", uosid, uuid); if (!syncHelperInter.isValid()) { return false; } QString ubid; - if (retLocalBindCheck.error().message().isEmpty()) { + if (retLocalBindCheck.isValid()) { ubid = retLocalBindCheck.value(); if (m_bindCheckTimer) { m_bindCheckTimer->stop(); } } else { - qWarning() << "UOSID:" << uosid << "uuid:" << uuid; - qWarning() << retLocalBindCheck.error().message(); + qCWarning(DDE_SHELL) << "UOSID:" << uosid << "uuid:" << uuid; + qCWarning(DDE_SHELL) << "Local bind check is invalid, error: " << retLocalBindCheck.error().message(); if (retLocalBindCheck.error().message().contains("network error")) { if (m_bindCheckTimer == nullptr) { m_bindCheckTimer = new QTimer(this); connect(m_bindCheckTimer, &QTimer::timeout, this, [this] { - qWarning() << "BindCheck retry!"; - if(isUserAccountBinded()) { + qCWarning(DDE_SHELL) << "BindCheck retry!"; + if (isUserAccountBinded()) { setResetPasswordMessageVisible(true); updateResetPasswordUI(); } @@ -573,11 +854,18 @@ void AuthPassword::updateResetPasswordUI() return; } +#ifndef ENABLE_DSS_SNIPE if (m_resetPasswordMessageVisible) { showResetPasswordMessage(); } else { closeResetPasswordMessage(); } +#endif +} + +bool AuthPassword::isShowResetPasswordMessage() +{ + return QFile::exists(DEEPIN_DEEPINID_DAEMON_PATH) && QFile::exists(ResetPassword_Exe_Path) && m_currentUid <= 9999 && !IsCommunitySystem; } bool AuthPassword::eventFilter(QObject *watched, QEvent *event) @@ -590,6 +878,21 @@ bool AuthPassword::eventFilter(QObject *watched, QEvent *event) return true; } } + + if (watched == m_iconButton && event->type() == QEvent::Paint) { + QPainter painter(m_iconButton); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + + if (!m_iconButton->icon().isNull()) { + QRect iconRect(0, 0, 20, 20); + iconRect.moveCenter(m_iconButton->rect().center()); + m_iconButton->icon().paint(&painter, iconRect); + } + + return true; + } + return false; } @@ -597,7 +900,197 @@ void AuthPassword::hideEvent(QHideEvent *event) { m_lineEdit->setAlert(false); m_lineEdit->hideAlertMessage(); + hidePasswordHintWidget(); setLineEditInfo(tr("Password"), PlaceHolderText); closeResetPasswordMessage(); + m_passwordTipsWidget->hide(); AuthModule::hideEvent(event); } + +void AuthPassword::showEvent(QShowEvent *event) +{ + m_passwordHintBtn->setVisible(m_limitsInfo->numFailures > 0 && !m_passwordHint.isEmpty()); + updatePasswordTextMargins(); + if (m_limitsInfo->numFailures >= 3) { + if (m_limitsInfo->locked) { + setAuthState(AS_Locked, "Locked"); + } + + if (isShowResetPasswordMessage()) { + qCDebug(DDE_SHELL) << "Begin reset passoword"; + setResetPasswordMessageVisible(true); + updateResetPasswordUI(); + } + } else { + setResetPasswordMessageVisible(false); + updateResetPasswordUI(); + } + + if (canShowPasswrodErrorTip()) { + QTimer::singleShot(0, this, [ = ] { + updatePasswrodErrorTipUi(); + }); + } + + AuthModule::showEvent(event); +} + +void AuthPassword::setAuthStatueVisible(bool visible) +{ + m_showAuthState = visible; + m_authStateLabel->setVisible(visible && !hasFocus()); + updatePasswordTextMargins(); +} + +void AuthPassword::showAlertMessage(const QString &text) +{ + hidePasswordHintWidget(); + m_lineEdit->showAlertMessage(text, this, 5000); +} + +void AuthPassword::hidePasswordHintWidget() +{ + if (m_passwordHintWidget) { + m_passwordHintWidget->deleteLater(); + m_passwordHintWidget = nullptr; + } + + // 恢复调色板 + DPaletteHelper::instance()->resetPalette(this->topLevelWidget()); +} + +void AuthPassword::updatePasswordTextMargins() +{ + QMargins textMargins = m_lineEdit->lineEdit()->textMargins(); + // 右边控件宽度+控件间距 + const int rightWidth = (m_passwordShowBtn->isVisible() ? m_passwordShowBtn->width() + 5 : 0) + (m_authStateLabel->isVisible() ? m_authStateLabel->width() + 5 : 0) + (m_passwordHintBtn->isVisible() ? m_passwordHintBtn->width() + 5 : 0); + // 左侧控件宽度 + const int leftWidth = (m_capsLock->isVisible() ? m_capsLock->width() + 5 : 0); + textMargins.setRight(rightWidth); +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + const int displayTextWidth = m_lineEdit->lineEdit()->fontMetrics().horizontalAdvance(m_lineEdit->lineEdit()->displayText()); +#else + const int displayTextWidth = m_lineEdit->lineEdit()->fontMetrics().width(m_lineEdit->lineEdit()->displayText()); +#endif + // 计算当前文字长度+图标+间距所需长度 和 编辑框长度的差值,如果空间不足,则缩减左边的margin,但是不小于左侧控件的宽度 + const int diff = m_lineEdit->lineEdit()->width() - 10 /*borer padding等宽度*/ - (displayTextWidth + 15 /*content margin*/ + textMargins.right() * 2); + textMargins.setLeft(qMax(leftWidth, rightWidth + (diff < 0 ? diff : 0))); + if (textMargins == m_lineEdit->lineEdit()->textMargins()) { + return; + } + + m_lineEdit->lineEdit()->setTextMargins(textMargins); +} + +void AuthPassword::updatePluginConfig() +{ + if (m_assistLoginWidget && m_isPasswdAuthWidgetReplaced) { + m_assistLoginWidget->updateConfig(); + } +} + +void AuthPassword::hidePlugin() +{ + if (m_assistLoginWidget == nullptr) { + return; + } + m_isPasswdAuthWidgetReplaced = false; + m_assistLoginWidget->hide(); + m_lineEdit->show(); + + Q_EMIT requestHidePlugin(); +} + +void AuthPassword::startPluginAuth() +{ + if (m_assistLoginWidget) { + m_assistLoginWidget->startAuth(); + } +} + +bool AuthPassword::isShowPasswrodErrorTip() +{ + return m_passwordTipsWidget->isVisible(); +} + +void AuthPassword::showErrorTip(const QString &text) +{ + if (canShowPasswrodErrorTip()) { + m_lineEdit->hideAlertMessage(); + m_lineEdit->setAlert(false); + m_passwordTipsWidget->setErrorTips(text); + m_passwordTipsWidget->setVisible(isVisible()); + } else { + m_lineEdit->showAlertMessage(text, this, 5000); + m_lineEdit->setAlert(true); + } +} + +void AuthPassword::clearPasswrodErrorTip(bool isClear) +{ + if (isClear) { + m_passwordTipsWidget->reset(); + } +} + +void AuthPassword::updatePasswrodErrorTipUi() +{ + m_passwordTipsWidget->setVisible(m_passwordTipsWidget->hasErrorTips()); + QRect rc = m_lineEdit->geometry(); + + QPoint pt(rc.x(), rc.y() + rc.height() +5); + + pt = m_lineEdit->mapToGlobal(pt); + m_passwordTipsWidget->move(pt); +} + +void AuthPassword::resizeEvent(QResizeEvent *event) +{ + qInfo() << Q_FUNC_INFO << event->size() << event->oldSize(); + if (canShowPasswrodErrorTip()) { + QTimer::singleShot(0, this, [ = ] { + updatePasswrodErrorTipUi(); + }); + } + QWidget::resizeEvent(event); +} + +void AuthPassword::moveEvent(QMoveEvent *event) +{ + qInfo() << Q_FUNC_INFO << event->pos() << event->oldPos(); + if (canShowPasswrodErrorTip()) { + QTimer::singleShot(0, this, [ = ] { + updatePasswrodErrorTipUi(); + }); + } + QWidget::moveEvent(event); +} + +void AuthPassword::onReadyToAuthChanged(bool ready) +{ + ready ? emit lineEditTextChanged(m_lineEdit->text()) : emit lineEditTextChanged(""); +} + + +QString AuthPassword::getCurrentKBLayout() const +{ + QProcess p; + p.start("/usr/bin/setxkbmap", {"-query"}); + p.waitForFinished(); + + const QString output = QString::fromUtf8(p.readAllStandardOutput()); + for (const QString &line : output.split('\n')) { + if (line.startsWith("layout:")) { + QString layout = line.section(':', 1).trimmed(); + return layout; + } + } + + return {}; +} + +void AuthPassword::setKBLayout(const QString &layout) +{ + qCDebug(DDE_SHELL) << "Set keyboard layout: " << layout; + QProcess::execute("/usr/bin/setxkbmap", { layout}); +} \ No newline at end of file diff --git a/src/session-widgets/auth_password.h b/src/session-widgets/auth_password.h index 3b876260..abac1956 100644 --- a/src/session-widgets/auth_password.h +++ b/src/session-widgets/auth_password.h @@ -1,28 +1,13 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHPASSWORD_H #define AUTHPASSWORD_H #include "auth_module.h" +#include "assist_login_widget.h" +#include "passworderrortipswidget.h" #include #include @@ -30,9 +15,9 @@ #include #include #include +#include #define Password_Auth QStringLiteral(":/misc/images/auth/password.svg") -//const QString Password_Auth = ":/misc/images/auth/password.svg"; class DLineEditEx; DWIDGET_USE_NAMESPACE @@ -42,12 +27,16 @@ class AuthPassword : public AuthModule Q_OBJECT public: explicit AuthPassword(QWidget *parent = nullptr); + ~AuthPassword() override; void reset(); QString lineEditText() const; + inline bool passwordLineEditEnabled() const { return m_passwordLineEditEnabled; } + void setPasswordLineEditEnabled(const bool enable); + void setAnimationState(const bool start) override; - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setCapsLockVisible(const bool on); void setLimitsInfo(const LimitsInfo &info) override; void setLineEditEnabled(const bool enable); @@ -56,6 +45,29 @@ class AuthPassword : public AuthModule void setCurrentUid(uid_t uid); void showResetPasswordMessage(); void closeResetPasswordMessage(); + void setAuthStatueVisible(bool visible); + + bool isShowResetPasswordMessage(); + void updatePluginConfig(); + void startPluginAuth(); + void hidePlugin(); + + bool isPasswdAuthWidgetReplaced() const + { + return m_isPasswdAuthWidgetReplaced; + } + + void setPasswdAuthWidgetReplaced(bool isPasswdAuthWidgetReplaced) + { + m_isPasswdAuthWidgetReplaced = isPasswdAuthWidgetReplaced; + } + bool isShowPasswrodErrorTip(); + inline bool canShowPasswrodErrorTip() { return m_canShowPasswordErrorTips; } + void showErrorTip(const QString &text); + void clearPasswrodErrorTip(bool isClear); + void updatePasswrodErrorTipUi(); + + AssistLoginWidget * assistLoginWidget() const { return m_assistLoginWidget; } signals: void focusChanged(const bool); @@ -63,14 +75,25 @@ class AuthPassword : public AuthModule void requestChangeFocus(); // 切换焦点 void requestShowKeyboardList(); // 显示键盘布局列表 void resetPasswordMessageVisibleChanged(const bool isVisible); + void notifyLockedStateChanged(bool isLocked); + void requestPluginConfigChanged(const LoginPlugin::PluginConfig &PluginConfig); + void requestHidePlugin(); + void requestPluginAuthToken(const QString accout, const QString token); + void requestUpdateBlurEffectGeometry(); + void passwordErrorTipsClearChanged(const bool isClear); + void requestSendExtraInfo(const QString &info); public slots: - void setResetPasswordMessageVisible(const bool isVisible); + void setResetPasswordMessageVisible(const bool isVisible, bool fromResetDialog = false); void updateResetPasswordUI(); + void onReadyToAuthChanged(bool ready); protected: bool eventFilter(QObject *watched, QEvent *event) override; void hideEvent(QHideEvent *event) override; + void showEvent(QShowEvent *event) override; + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void moveEvent(QMoveEvent *event) Q_DECL_OVERRIDE; private: void initUI(); @@ -79,16 +102,33 @@ public slots: void showPasswordHint(); void setPasswordHintBtnVisible(const bool isVisible); bool isUserAccountBinded(); + void showAlertMessage(const QString &text); + void hidePasswordHintWidget(); + void updatePasswordTextMargins(); + QString getCurrentKBLayout() const; + void setKBLayout(const QString &layout); private: + bool m_passwordLineEditEnabled; DLabel *m_capsLock; // 大小写状态 DLineEditEx *m_lineEdit; // 密码输入框 + DIconButton *m_passwordShowBtn; // 密码显示按钮 DIconButton *m_passwordHintBtn; // 密码提示按钮 + PasswordErrorTipsWidget* m_passwordTipsWidget; // 认证错误提示窗口 QString m_passwordHint; // 密码提示 bool m_resetPasswordMessageVisible; DFloatingMessage *m_resetPasswordFloatingMessage; uid_t m_currentUid; // 当前用户uid QTimer *m_bindCheckTimer; + DAlertControl *m_passwordHintWidget; + DIconButton *m_iconButton; + bool m_resetDialogShow; + + bool m_isPasswdAuthWidgetReplaced; + AssistLoginWidget *m_assistLoginWidget; + DConfig *m_authenticationDconfig; + bool m_canShowPasswordErrorTips; + QString m_originalKBLayout; }; #endif // AUTHPASSWORD_H diff --git a/src/session-widgets/auth_single.cpp b/src/session-widgets/auth_single.cpp index 782686f4..02f06456 100644 --- a/src/session-widgets/auth_single.cpp +++ b/src/session-widgets/auth_single.cpp @@ -1,49 +1,26 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_single.h" #include "authcommon.h" #include "dlineeditex.h" +#include "dbusconstant.h" #include +#include #include -#include -#include -#include -#include -#include -#include #include #include +#ifndef ENABLE_DSS_SNIPE #include -#include #include - -#define Service "com.deepin.dialogs.ResetPassword" -#define Path "/com/deepin/dialogs/ResetPassword" -#define Interface "com.deepin.dialogs.ResetPassword" - +#else +#include "userinterface.h" +#endif using namespace AuthCommon; AuthSingle::AuthSingle(QWidget *parent) @@ -55,6 +32,7 @@ AuthSingle::AuthSingle(QWidget *parent) , m_resetPasswordMessageVisible(false) , m_resetPasswordFloatingMessage(nullptr) , m_bindCheckTimer(nullptr) + , m_iconButton(nullptr) { setObjectName(QStringLiteral("AuthSingle")); setAccessibleName(QStringLiteral("AuthSingle")); @@ -63,6 +41,8 @@ AuthSingle::AuthSingle(QWidget *parent) initConnections(); m_lineEdit->installEventFilter(this); + m_lineEdit->setCopyEnabled(false); + m_lineEdit->setCutEnabled(false); setFocusProxy(m_lineEdit); } @@ -71,18 +51,23 @@ AuthSingle::AuthSingle(QWidget *parent) */ void AuthSingle::initUI() { - QHBoxLayout *mainLayout = new QHBoxLayout(this); + auto *mainLayout = new QHBoxLayout(this); mainLayout->setSpacing(0); mainLayout->setContentsMargins(0, 0, 0, 0); m_lineEdit->setClearButtonEnabled(false); m_lineEdit->setEchoMode(QLineEdit::Password); + m_lineEdit->setSecureInputEnabled(true); m_lineEdit->setContextMenuPolicy(Qt::NoContextMenu); m_lineEdit->setFocusPolicy(Qt::StrongFocus); m_lineEdit->lineEdit()->setAlignment(Qt::AlignCenter); - m_lineEdit->lineEdit()->setValidator(new QRegExpValidator(QRegExp("^[ -~]+$"))); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_lineEdit->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression("^[ -~]+$"))); +#else + m_lineEdit->lineEdit()->setValidator(new QRegExpValidator(QRegExp("^[ -~]+$"), this)); +#endif - QHBoxLayout *passwordLayout = new QHBoxLayout(m_lineEdit->lineEdit()); + auto *passwordLayout = new QHBoxLayout(m_lineEdit->lineEdit()); passwordLayout->setContentsMargins(0, 0, 10, 0); passwordLayout->setSpacing(0); /* 键盘布局按钮 */ @@ -108,9 +93,11 @@ void AuthSingle::initUI() m_passwordHintBtn->setFlat(true); m_passwordHintBtn->setIcon(QIcon(PASSWORD_HINT)); m_passwordHintBtn->setIconSize(QSize(16, 16)); + m_passwordHintBtn->setVisible(false); passwordLayout->addWidget(m_passwordHintBtn, 0, Qt::AlignRight | Qt::AlignVCenter); mainLayout->addWidget(m_lineEdit); + updatePasswordTextMargins(); } /** @@ -151,7 +138,7 @@ void AuthSingle::initConnections() */ void AuthSingle::reset() { - m_lineEdit->clear(); + m_lineEdit->setText(QString()); m_lineEdit->setAlert(false); m_lineEdit->hideAlertMessage(); setLineEditEnabled(true); @@ -163,22 +150,22 @@ void AuthSingle::reset() * @param state * @param result */ -void AuthSingle::setAuthState(const int state, const QString &result) +void AuthSingle::setAuthState(const AuthCommon::AuthState state, const QString &result) { - qDebug() << "AuthSingle::setAuthResult:" << state << result; + qCDebug(DDE_SHELL) << "Set auth state, state: " << state << ", result: " << result; m_state = state; switch (state) { case AS_Success: setAnimationState(false); m_lineEdit->setAlert(false); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); setLineEditEnabled(false); setLineEditInfo(result, PlaceHolderText); emit authFinished(AS_Success); break; case AS_Failure: { setAnimationState(false); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); if (m_limitsInfo->locked) { m_lineEdit->setAlert(false); setLineEditEnabled(false); @@ -215,7 +202,7 @@ void AuthSingle::setAuthState(const int state, const QString &result) break; case AS_Prompt: setAnimationState(false); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); setLineEditEnabled(true); setLineEditInfo(result, PlaceHolderText); break; @@ -234,7 +221,7 @@ void AuthSingle::setAuthState(const int state, const QString &result) default: setAnimationState(false); setLineEditInfo(result, AlertText); - qWarning() << "Error! The state of Password Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "The state of password auth is wrong, state:" << state << ", result: " << result; break; } update(); @@ -248,6 +235,7 @@ void AuthSingle::setAuthState(const int state, const QString &result) void AuthSingle::setCapsLockVisible(const bool on) { m_capsLock->setVisible(on); + updatePasswordTextMargins(); } /** @@ -267,14 +255,15 @@ void AuthSingle::setAnimationState(const bool start) */ void AuthSingle::setLimitsInfo(const LimitsInfo &info) { - qDebug() << "AuthSingle::setLimitsInfo" << info.unlockTime; + qCDebug(DDE_SHELL) << "Set limits info: " << info.numFailures; const bool lockStateChanged = (info.locked != m_limitsInfo->locked); AuthModule::setLimitsInfo(info); setPasswordHintBtnVisible(info.numFailures > 0 && !m_passwordHint.isEmpty()); - if (m_limitsInfo->locked) { - if (lockStateChanged && this->isVisible() && QFile::exists(ResetPassword_Exe_Path) && - m_currentUid <= 9999) { - qDebug() << "begin reset passoword"; + if (m_limitsInfo->numFailures >= 3) { + bool isShow = lockStateChanged && this->isVisible() && QFile::exists(DEEPIN_DEEPINID_DAEMON_PATH) && + QFile::exists(ResetPassword_Exe_Path) && m_currentUid <= 9999 && !IsCommunitySystem; + if (isShow) { + qCDebug(DDE_SHELL) << "Begin reset passoword"; setResetPasswordMessageVisible(true); updateResetPasswordUI(); } @@ -292,17 +281,30 @@ void AuthSingle::setLimitsInfo(const LimitsInfo &info) void AuthSingle::setLineEditEnabled(const bool enable) { // m_lineEdit->setEnabled(enable); - if (enable) { + if (!m_passwordLineEditEnabled) { + m_lineEdit->setFocusPolicy(Qt::NoFocus); + m_lineEdit->clearFocus(); + m_lineEdit->lineEdit()->setReadOnly(true); + m_lineEdit->lineEdit()->setEnabled(false); + } else if (enable) { m_lineEdit->setFocusPolicy(Qt::StrongFocus); m_lineEdit->setFocus(); m_lineEdit->lineEdit()->setReadOnly(false); + m_lineEdit->lineEdit()->setEnabled(true); } else { m_lineEdit->setFocusPolicy(Qt::NoFocus); m_lineEdit->clearFocus(); m_lineEdit->lineEdit()->setReadOnly(true); + m_lineEdit->lineEdit()->setEnabled(true); } } +void AuthSingle::setPasswordLineEditEnabled(const bool enable) +{ + m_passwordLineEditEnabled = enable; + setLineEditEnabled(enable); +} + /** * @brief 设置输入框中的文案 * @@ -380,8 +382,8 @@ void AuthSingle::setResetPasswordMessageVisible(const bool isVisible) if (m_resetPasswordMessageVisible == isVisible) return; - // 如果设置为显示重置按钮,但是实际上并没有锁定,直接退出,是是否锁定为准 - if (isVisible && !isLocked()) + // 如果设置为显示重置按钮,失败次数>=3次就显示重置密码:1060-24505 + if (isVisible && m_limitsInfo && m_limitsInfo->numFailures < 3) return; m_resetPasswordMessageVisible = isVisible; @@ -403,7 +405,7 @@ QString AuthSingle::lineEditText() const */ void AuthSingle::updateUnlockPrompt() { - qDebug() << "AuthSingle::updateUnlockPrompt:" << m_integerMinutes; + qCDebug(DDE_SHELL) << "Update unlock prompt, integer minutes: " << m_integerMinutes; if (m_integerMinutes == 1) { m_lineEdit->setPlaceholderText(tr("Please try again 1 minute later")); } else if (m_integerMinutes > 1) { @@ -412,7 +414,7 @@ void AuthSingle::updateUnlockPrompt() QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } @@ -432,6 +434,7 @@ void AuthSingle::showPasswordHint() void AuthSingle::setPasswordHintBtnVisible(const bool isVisible) { m_passwordHintBtn->setVisible(isVisible); + updatePasswordTextMargins(); } /** @@ -454,23 +457,42 @@ void AuthSingle::showResetPasswordMessage() } QPalette pa; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + pa.setColor(QPalette::Window, QColor(247, 247, 247, 51)); +#else pa.setColor(QPalette::Background, QColor(247, 247, 247, 51)); +#endif + pa.setColor(QPalette::Highlight, Qt::white); + pa.setColor(QPalette::HighlightedText, Qt::black); m_resetPasswordFloatingMessage = new DFloatingMessage(DFloatingMessage::MessageType::ResidentType); m_resetPasswordFloatingMessage->setPalette(pa); - m_resetPasswordFloatingMessage->setIcon(QIcon::fromTheme("dialog-warning")); + // DFloatingMessage 中未放开seticonsize接口,无法设置图标大小,使用缩放会造成图标锯齿 + // 只能使用findChildren找到对应的图标控件来设置图标大小进行规避 + // DFloatingMessage中有两个按钮一个是DIconButton,另一个是继承于DIconButton的DDialogCloseButton,需要区分 + QList btnList = m_resetPasswordFloatingMessage->findChildren(); + foreach (const auto iconButton, btnList) { + DDialogCloseButton * closeButton = qobject_cast(iconButton); + if (closeButton) { + continue; + } + iconButton->installEventFilter(this); + m_iconButton = iconButton; + } + m_resetPasswordFloatingMessage->setIcon(QIcon("://misc/images/dss_warning.svg")); DSuggestButton *suggestButton = new DSuggestButton(tr("Reset Password")); + suggestButton->setAutoDefault(true); m_resetPasswordFloatingMessage->setWidget(suggestButton); m_resetPasswordFloatingMessage->setMessage(tr("Forgot password?")); - connect(suggestButton, &QPushButton::clicked, this, [ this ]{ - if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(false)) { - qDebug() << "setKeyboardGrabEnabled(false) success!"; - } - const QString AccountsService("com.deepin.daemon.Accounts"); - const QString path = QString("/com/deepin/daemon/Accounts/User%1").arg(m_currentUid); - com::deepin::daemon::accounts::User user(AccountsService, path, QDBusConnection::systemBus()); + connect(suggestButton, &QPushButton::clicked, this, [this]{ +#ifndef ENABLE_DSS_SNIPE + com::deepin::daemon::accounts::User +#else + org::deepin::dde::accounts1::User +#endif + user(DSS_DBUS::accountsService, QString(DSS_DBUS::accountsUserPath).arg(m_currentUid), QDBusConnection::systemBus()); auto reply = user.SetPassword(""); reply.waitForFinished(); - qWarning() << "reply setpassword:" << reply.error().message(); + qCWarning(DDE_SHELL) << "Show reset password message: " << reply.error().message(); emit m_resetPasswordFloatingMessage->closeButtonClicked(); }); @@ -510,16 +532,16 @@ bool AuthSingle::isUserAccountBinded() return false; } QString uosid; - if (retUOSID.error().message().isEmpty()) { + if (retUOSID.isValid()) { uosid = retUOSID.value(); } else { - qWarning() << retUOSID.error().message(); + qCWarning(DDE_SHELL) << "UOS ID is invalid, error: " << retUOSID.error().message(); return false; } - QDBusInterface accountsInter("com.deepin.daemon.Accounts", - QString("/com/deepin/daemon/Accounts/User%1").arg(m_currentUid), - "com.deepin.daemon.Accounts.User", + QDBusInterface accountsInter(DSS_DBUS::accountsService, + QString(DSS_DBUS::accountsUserPath).arg(m_currentUid), + DSS_DBUS::accountsUserInterface, QDBusConnection::systemBus()); QVariant retUUID = accountsInter.property("UUID"); if (!accountsInter.isValid()) { @@ -532,19 +554,18 @@ bool AuthSingle::isUserAccountBinded() return false; } QString ubid; - if (retLocalBindCheck.error().message().isEmpty()) { + if (retLocalBindCheck.isValid()) { ubid = retLocalBindCheck.value(); if (m_bindCheckTimer) { m_bindCheckTimer->stop(); } } else { - qWarning() << "UOSID:" << uosid << "uuid:" << uuid; - qWarning() << retLocalBindCheck.error().message(); + qCWarning(DDE_SHELL) << "Local bind check is invalid, UOSID:" << uosid << ", uuid:" << uuid << ", error: " << retLocalBindCheck.error().message(); if (retLocalBindCheck.error().message().contains("network error")) { if (m_bindCheckTimer == nullptr) { m_bindCheckTimer = new QTimer(this); connect(m_bindCheckTimer, &QTimer::timeout, this, [this] { - qWarning() << "BindCheck retry!"; + qCWarning(DDE_SHELL) << "BindCheck retry!"; if(isUserAccountBinded()) { setResetPasswordMessageVisible(true); updateResetPasswordUI(); @@ -564,6 +585,15 @@ bool AuthSingle::isUserAccountBinded() } } +void AuthSingle::updatePasswordTextMargins() +{ + // 根据大小写提示是否显示,设置密码框左边距,根据密码提示和显示密码设置密码杠右边距 + QMargins textMargins = m_lineEdit->lineEdit()->textMargins(); + textMargins.setLeft(m_capsLock->isVisible() ? m_capsLock->width() : 0); + textMargins.setRight(m_passwordHintBtn->isVisible() ? m_passwordHintBtn->width() : 0); + m_lineEdit->lineEdit()->setTextMargins(textMargins); +} + /** * @brief 更新重置密码UI相关状态 */ @@ -573,11 +603,13 @@ void AuthSingle::updateResetPasswordUI() return; } +#ifndef ENABLE_DSS_SNIPE if (m_resetPasswordMessageVisible) { showResetPasswordMessage(); } else { closeResetPasswordMessage(); } +#endif } bool AuthSingle::eventFilter(QObject *watched, QEvent *event) @@ -595,5 +627,19 @@ bool AuthSingle::eventFilter(QObject *watched, QEvent *event) closeResetPasswordMessage(); } + if (watched == m_iconButton && event->type() == QEvent::Paint) { + QPainter painter(m_iconButton); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + + if (!m_iconButton->icon().isNull()) { + QRect iconRect(0, 0, 20, 20); + iconRect.moveCenter(m_iconButton->rect().center()); + m_iconButton->icon().paint(&painter, iconRect); + } + + return true; + } + return false; } diff --git a/src/session-widgets/auth_single.h b/src/session-widgets/auth_single.h index 85976522..ab83cb38 100644 --- a/src/session-widgets/auth_single.h +++ b/src/session-widgets/auth_single.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHSINGLE_H #define AUTHSINGLE_H @@ -40,8 +23,11 @@ class AuthSingle : public AuthModule void reset(); QString lineEditText() const; + inline bool passwordLineEditEnabled() const { return m_passwordLineEditEnabled; } + void setPasswordLineEditEnabled(const bool enable); + void setAnimationState(const bool start) override; - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setCapsLockVisible(const bool on); void setKeyboardButtonInfo(const QString &text); void setKeyboardButtonVisible(const bool visible); @@ -68,11 +54,14 @@ public slots: void initUI(); void initConnections(); - void updateUnlockPrompt(); + void updateUnlockPrompt() override; void showPasswordHint(); void setPasswordHintBtnVisible(const bool isVisible); bool isUserAccountBinded(); + void updatePasswordTextMargins(); + private: + bool m_passwordLineEditEnabled; DLabel *m_capsLock; // 大小写状态 DLineEditEx *m_lineEdit; // 输入框 DPushButton *m_keyboardBtn; // 键盘布局按钮 @@ -82,6 +71,7 @@ public slots: DFloatingMessage *m_resetPasswordFloatingMessage; uid_t m_currentUid; // 当前用户uid QTimer *m_bindCheckTimer; + DIconButton *m_iconButton; }; #endif // AUTHSINGLE_H diff --git a/src/session-widgets/auth_ukey.cpp b/src/session-widgets/auth_ukey.cpp index 3cd14fe3..2f86e7ba 100644 --- a/src/session-widgets/auth_ukey.cpp +++ b/src/session-widgets/auth_ukey.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_ukey.h" @@ -55,6 +38,7 @@ void AuthUKey::initUI() m_lineEdit->setClearButtonEnabled(false); m_lineEdit->setEchoMode(QLineEdit::Password); + m_lineEdit->setSecureInputEnabled(true); m_lineEdit->setContextMenuPolicy(Qt::NoContextMenu); m_lineEdit->setFocusPolicy(Qt::StrongFocus); m_lineEdit->lineEdit()->setAlignment(Qt::AlignCenter); @@ -72,6 +56,7 @@ void AuthUKey::initUI() UKeyLayout->addWidget(m_capsLock, 0, Qt::AlignRight | Qt::AlignVCenter); /* 认证状态 */ m_authStateLabel = new DLabel(m_lineEdit); + m_authStateLabel->setVisible(false); setAuthStateStyle(LOGIN_WAIT); UKeyLayout->addWidget(m_authStateLabel, 0, Qt::AlignRight | Qt::AlignVCenter); @@ -87,7 +72,7 @@ void AuthUKey::initConnections() /* PIN 码输入框 */ connect(m_lineEdit, &DLineEditEx::focusChanged, this, [this](const bool focus) { if (!focus) m_lineEdit->setAlert(false); - m_authStateLabel->setVisible(!focus); + m_authStateLabel->setVisible(!focus && m_showAuthState); emit focusChanged(focus); }); connect(m_lineEdit, &DLineEditEx::textChanged, this, [this](const QString &text) { @@ -95,7 +80,7 @@ void AuthUKey::initConnections() m_lineEdit->hideAlertMessage(); emit lineEditTextChanged(text); }); - connect(m_lineEdit, &DLineEditEx::returnPressed, this, [ this ] { + connect(m_lineEdit, &DLineEditEx::returnPressed, this, [this] { if (!m_lineEdit->lineEdit()->isReadOnly()) emit requestAuthenticate(); }); @@ -106,7 +91,7 @@ void AuthUKey::initConnections() */ void AuthUKey::reset() { - m_lineEdit->clear(); + m_lineEdit->setText(QString()); m_lineEdit->setAlert(false); m_lineEdit->hideAlertMessage(); setLineEditEnabled(true); @@ -119,16 +104,15 @@ void AuthUKey::reset() * @param state * @param result */ -void AuthUKey::setAuthState(const int state, const QString &result) +void AuthUKey::setAuthState(const AuthCommon::AuthState state, const QString &result) { - qDebug() << "AuthUKey::setAuthResult:" << state << result; m_state = state; switch (state) { case AuthCommon::AS_Success: setAnimationState(false); setAuthStateStyle(LOGIN_CHECK); m_lineEdit->setAlert(false); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); setLineEditEnabled(false); setLineEditInfo(tr("Verification successful"), PlaceHolderText); m_showPrompt = true; @@ -139,7 +123,7 @@ void AuthUKey::setAuthState(const int state, const QString &result) case AuthCommon::AS_Failure: setAnimationState(false); setAuthStateStyle(LOGIN_WAIT); - m_lineEdit->clear(); + m_lineEdit->setText(QString()); m_lineEdit->setFocus(); if (m_limitsInfo->locked) { m_lineEdit->setAlert(false); @@ -216,7 +200,7 @@ void AuthUKey::setAuthState(const int state, const QString &result) setAuthStateStyle(LOGIN_WAIT); setLineEditInfo(result, AlertText); m_showPrompt = true; - qWarning() << "Error! The state of UKey Auth is wrong!" << state << result; + qCWarning(DDE_SHELL) << "The state of ukey auth is wrong, state:" << state << ", result: " << result; break; } update(); @@ -249,7 +233,7 @@ void AuthUKey::setCapsLockVisible(const bool on) */ void AuthUKey::setLimitsInfo(const LimitsInfo &info) { - qDebug() << "AuthUKey::setLimitsInfo" << info.unlockTime; + qCDebug(DDE_SHELL) << "Set limits info: " << info.numFailures; AuthModule::setLimitsInfo(info); } @@ -321,7 +305,7 @@ void AuthUKey::updateUnlockPrompt() QTimer::singleShot(1000, this, [this] { emit activeAuth(m_type); }); - qInfo() << "Waiting authentication service..."; + qCInfo(DDE_SHELL) << "Waiting authentication service..."; } update(); } @@ -347,3 +331,9 @@ void AuthUKey::hide() setLineEditInfo(tr("Enter your PIN"), PlaceHolderText); AuthModule::hide(); } + +void AuthUKey::setAuthStatueVisible(bool visible) +{ + m_showAuthState = visible; + m_authStateLabel->setVisible(visible && !hasFocus()); +} diff --git a/src/session-widgets/auth_ukey.h b/src/session-widgets/auth_ukey.h index 6ce8b5b1..33c0b64b 100644 --- a/src/session-widgets/auth_ukey.h +++ b/src/session-widgets/auth_ukey.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef AUTHUKEY_H #define AUTHUKEY_H @@ -21,12 +25,13 @@ class AuthUKey : public AuthModule QString lineEditText() const; void setAnimationState(const bool start) override; - void setAuthState(const int state, const QString &result) override; + void setAuthState(const AuthCommon::AuthState state, const QString &result) override; void setCapsLockVisible(const bool on); void setLimitsInfo(const LimitsInfo &info) override; void setLineEditEnabled(const bool enable); void setLineEditInfo(const QString &text, const TextType type); void hide(); + void setAuthStatueVisible(bool visible); signals: void focusChanged(const bool); diff --git a/src/session-widgets/auth_widget.cpp b/src/session-widgets/auth_widget.cpp index 62f119de..b2679f53 100644 --- a/src/session-widgets/auth_widget.cpp +++ b/src/session-widgets/auth_widget.cpp @@ -1,66 +1,50 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "auth_widget.h" #include "auth_face.h" #include "auth_fingerprint.h" #include "auth_iris.h" +#include "auth_passkey.h" #include "auth_password.h" #include "auth_single.h" #include "auth_ukey.h" +#include "auth_custom.h" #include "dlineeditex.h" -#include "framedatabind.h" #include "keyboardmonitor.h" #include "sessionbasemodel.h" #include "useravatar.h" +#include "dconfig_helper.h" #include const int BlurRadius = 15; const int BlurTransparency = 70; -const int EXPIRED_SPACER_ITEM_HEIGHT = 10; const QColor ShutdownColor(QColor(247, 68, 68)); AuthWidget::AuthWidget(QWidget *parent) : QWidget(parent) , m_model(nullptr) - , m_frameDataBind(FrameDataBind::Instance()) , m_blurEffectWidget(new DBlurEffectWidget(this)) - , m_lockButton(nullptr) + , m_lockButton(new TransparentButton(this)) , m_userAvatar(nullptr) , m_expiredStateLabel(new DLabel(this)) - , m_expiredSpacerItem(new QSpacerItem(0, 0)) - , m_nameLabel(nullptr) , m_accountEdit(nullptr) - , m_capslockMonitor(nullptr) - , m_keyboardTypeClip(nullptr) + , m_userNameWidget(nullptr) , m_singleAuth(nullptr) , m_passwordAuth(nullptr) , m_fingerprintAuth(nullptr) , m_ukeyAuth(nullptr) , m_faceAuth(nullptr) , m_irisAuth(nullptr) + , m_passkeyAuth(nullptr) + , m_gestureAuth(nullptr) , m_customAuth(nullptr) + , m_refreshTimer(new QTimer(this)) + , m_authState(AuthCommon::AS_None) { setObjectName(QStringLiteral("AuthWidget")); setAccessibleName(QStringLiteral("AuthWidget")); @@ -68,16 +52,19 @@ AuthWidget::AuthWidget(QWidget *parent) setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setFocusPolicy(Qt::NoFocus); - m_capslockMonitor = KeyboardMonitor::instance(); - m_capslockMonitor->start(QThread::LowestPriority); - m_frameDataBind = FrameDataBind::Instance(); + m_refreshTimer->setInterval(1000); + m_refreshTimer->start(); + connect(m_refreshTimer, &QTimer::timeout, this, [ this ] { + if(QTime::currentTime().minute() == 0 && QTime::currentTime().second() == 0){ + m_user->updatePasswordExpiredInfo(); + updatePasswordExpiredState(); + } + }); } AuthWidget::~AuthWidget() { - for (auto it = m_registerFunctions.constBegin(); it != m_registerFunctions.constEnd(); ++it) { - m_frameDataBind->unRegisterFunction(it.key(), it.value()); - } + } void AuthWidget::initUI() @@ -87,35 +74,39 @@ void AuthWidget::initUI() m_userAvatar->setFocusPolicy(Qt::NoFocus); m_userAvatar->setIcon(m_user->avatar()); m_userAvatar->setAvatarSize(UserAvatar::AvatarLargeSize); - /* 用户名 */ - m_nameLabel = new DLabel(this); - m_nameLabel->setAccessibleName(QStringLiteral("NameLabel")); - m_nameLabel->setTextFormat(Qt::TextFormat::PlainText); - m_nameLabel->setText(m_model->currentUser()->displayName()); - m_nameLabel->setAlignment(Qt::AlignCenter); - m_nameLabel->setTextFormat(Qt::TextFormat::PlainText); - DFontSizeManager::instance()->bind(m_nameLabel, DFontSizeManager::T2); - QPalette palette = m_nameLabel->palette(); - palette.setColor(QPalette::WindowText, Qt::white); - m_nameLabel->setPalette(palette); /* 用户名输入框 */ m_accountEdit = new DLineEditEx(this); m_accountEdit->setContextMenuPolicy(Qt::NoContextMenu); m_accountEdit->lineEdit()->setAlignment(Qt::AlignCenter); m_accountEdit->setClearButtonEnabled(false); m_accountEdit->setPlaceholderText(tr("Account")); + m_accountEdit->setEnableTableKeyEvent(true); + + // 账户名有效字符使用dsg配置 + const QString accountExpression = DConfigHelper::instance()->getConfig("accountExpression", "[a-zA-Z0-9-_@]+$").toString(); + if (!accountExpression.isEmpty()) { +#ifndef ENABLE_DSS_SNIPE + m_accountEdit->lineEdit()->setValidator(new QRegExpValidator(QRegExp(accountExpression), this)); +#else + m_accountEdit->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression(accountExpression), this)); +#endif + } + // 用户名 + m_userNameWidget = new UserNameWidget(false, true, this); /* 密码过期提示 */ m_expiredStateLabel->setAccessibleName("ExpiredStateLabel"); m_expiredStateLabel->setWordWrap(true); m_expiredStateLabel->setAlignment(Qt::AlignHCenter); - m_expiredStateLabel->hide(); + if (!m_model->terminalLocked()) { + m_expiredStateLabel->hide(); + } /* 解锁按钮 */ - m_lockButton = new DFloatingButton(this); if (m_model->appType() == Lock) { m_lockButton->setIcon(DStyle::SP_LockElement); } else { m_lockButton->setIcon(DStyle::SP_ArrowNext); } + m_lockButton->setAccessibleName("LockButton"); /* 模糊背景 */ m_blurEffectWidget->setMaskColor(DBlurEffectWidget::LightColor); m_blurEffectWidget->setMaskAlpha(BlurTransparency); @@ -131,20 +122,22 @@ void AuthWidget::initConnections() connect(m_model, &SessionBaseModel::onPowerActionChanged, this, [this](SessionBaseModel::PowerAction action) { setLockButtonType(action); }); + connect(m_model, &SessionBaseModel::checkAccountFinished, this, [this] { + m_accountEdit->clear(); + }); + /* 用户名 */ - connect(qGuiApp, &QGuiApplication::fontChanged, this, &AuthWidget::updateUserNameLabel); + connect(qGuiApp, &QGuiApplication::fontChanged, this, &AuthWidget::updateUserDisplayNameLabel); /* 用户名输入框 */ connect(m_accountEdit, &DLineEditEx::returnPressed, this, [this] { if (m_accountEdit->isVisible() && !m_accountEdit->text().isEmpty()) { - emit requestCheckAccount(m_accountEdit->text()); + emit requestCheckSameNameAccount(m_accountEdit->text()); } }); - connect(m_accountEdit, &DLineEditEx::editingFinished, this, [this] { - emit m_accountEdit->returnPressed(); - }); /* 解锁按钮 */ connect(m_lockButton, &DFloatingButton::clicked, this, [this] { - if (m_user->isNoPasswordLogin()) { + // 账户锁定后密码是无效的,这时开启快速登录会直接进入桌面,这里需要排除密码无效的情况 + if (m_user->isNoPasswordLogin() && m_user->isPasswordValid()) { emit requestCheckAccount(m_user->name()); } else if (!m_passwordAuth && !m_ukeyAuth && !m_singleAuth) { emit m_accountEdit->returnPressed(); @@ -156,6 +149,9 @@ void AuthWidget::setModel(const SessionBaseModel *model) { m_model = model; m_user = model->currentUser(); + + terminalLockedChanged(m_model->terminalLocked()); + connect(m_model, &SessionBaseModel::terminalLockedChanged, this, &AuthWidget::terminalLockedChanged); } /** @@ -170,25 +166,28 @@ void AuthWidget::setUser(std::shared_ptr user) m_connectionList.clear(); m_user = user; m_connectionList << connect(user.get(), &User::avatarChanged, this, &AuthWidget::setAvatar) - << connect(user.get(), &User::displayNameChanged, this, &AuthWidget::updateUserNameLabel) + << connect(user.get(), &User::displayNameChanged, this, &AuthWidget::updateUserDisplayNameLabel) << connect(user.get(), &User::passwordHintChanged, this, &AuthWidget::setPasswordHint) << connect(user.get(), &User::limitsInfoChanged, this, &AuthWidget::setLimitsInfo) << connect(user.get(), &User::passwordExpiredInfoChanged, this, &AuthWidget::updatePasswordExpiredState) - << connect(user.get(), &User::limitsInfoChanged, this, &AuthWidget::setLimitsInfo); + << connect(user.get(), &User::noPasswordLoginChanged, this, &AuthWidget::onNoPasswordLoginChanged); setAvatar(user->avatar()); setPasswordHint(user->passwordHint()); setLimitsInfo(user->limitsInfo()); - updatePasswordExpiredState(); - updateUserNameLabel(); + if (!m_model->terminalLocked()) { + updatePasswordExpiredState(); + } + updateUserDisplayNameLabel(); /* 根据用户类型设置用户名和用户名输入框的可见性 */ if (user->type() == User::Default) { - m_nameLabel->hide(); + m_userNameWidget->hide(); m_accountEdit->show(); + this->setFocusProxy(m_accountEdit); m_accountEdit->setFocus(); } else { - m_nameLabel->show(); + m_userNameWidget->show(); m_accountEdit->hide(); m_accountEdit->clear(); } @@ -199,13 +198,18 @@ void AuthWidget::setUser(std::shared_ptr user) if (m_passwordAuth) { m_passwordAuth->setCurrentUid(user->uid()); } + + // A账户为无密码登录,B账户有密码;在登录界面的时候,B账户输入密码不登录,切换到A,再切换到B,发现B的密码输入框还有密码。 + if (m_passwordAuth) { + m_passwordAuth->reset(); + } } /** * @brief 设置认证类型 * @param type */ -void AuthWidget::setAuthType(const int type) +void AuthWidget::setAuthType(const AuthCommon::AuthFlags type) { Q_UNUSED(type) } @@ -216,11 +220,13 @@ void AuthWidget::setAuthType(const int type) * @param state * @param message */ -void AuthWidget::setAuthState(const int type, const int state, const QString &message) +void AuthWidget::setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) { Q_UNUSED(type) Q_UNUSED(state) Q_UNUSED(message) + + m_authState = static_cast(state); } /** @@ -228,7 +234,7 @@ void AuthWidget::setAuthState(const int type, const int state, const QString &me * @param type * @param state */ -void AuthWidget::checkAuthResult(const int type, const int state) +void AuthWidget::checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state) { Q_UNUSED(type) Q_UNUSED(state) @@ -277,6 +283,11 @@ void AuthWidget::setLimitsInfo(const QMap *limitsInfo) m_faceAuth->setLimitsInfo(limitsInfoTmp); } break; + case AT_Passkey: + if (m_passkeyAuth) { + m_passkeyAuth->setLimitsInfo(limitsInfoTmp); + } + break; case AT_Iris: if (m_irisAuth) { m_irisAuth->setLimitsInfo(limitsInfoTmp); @@ -285,12 +296,21 @@ void AuthWidget::setLimitsInfo(const QMap *limitsInfo) case AT_ActiveDirectory: case AT_Custom: break; + case AT_Pattern: + if (m_gestureAuth) { + m_gestureAuth->setLimitsInfo(limitsInfoTmp); + } + break; default: - qWarning() << "Error! Authentication type is wrong." << i.key(); + qCWarning(DDE_SHELL) << "Authentication type is wrong." << i.key(); break; } ++i; } + + if (m_customAuth) { + m_customAuth->setLimitsInfo(*limitsInfo); + } } /** @@ -306,18 +326,11 @@ void AuthWidget::setAvatar(const QString &avatar) * @brief 设置用户名字体 * @param font */ -void AuthWidget::updateUserNameLabel() +void AuthWidget::updateUserDisplayNameLabel() { - const QString &name = m_user->displayName(); - int nameWidth = m_nameLabel->fontMetrics().boundingRect(name).width(); - int labelMaxWidth = width() - 10 * 2; - - if (nameWidth > labelMaxWidth) { - QString str = m_nameLabel->fontMetrics().elidedText(name, Qt::ElideRight, labelMaxWidth); - m_nameLabel->setText(str); - } else { - m_nameLabel->setText(name); - } + m_userNameWidget->updateFullName(m_user->fullName()); + m_userNameWidget->updateUserName(m_user->name()); + m_userNameWidget->setDomainUserVisible(m_user->isDomainUser()); } /** @@ -334,6 +347,14 @@ void AuthWidget::setPasswordHint(const QString &hint) } } +void AuthWidget::onNoPasswordLoginChanged(bool noPassword) +{ + if (noPassword) + setAuthType(AT_None); + + Q_EMIT noPasswordLoginChanged(m_user->name(), noPassword); +} + /** * @brief 设置解锁按钮的样式 * @param type @@ -344,11 +365,11 @@ void AuthWidget::setLockButtonType(const int type) switch (type) { case SessionBaseModel::RequireRestart: m_lockButton->setIcon(QIcon(":/img/bottom_actions/reboot.svg")); - lockPalette.setColor(QPalette::Highlight, ShutdownColor); + m_lockButton->setColor(ShutdownColor); break; case SessionBaseModel::RequireShutdown: m_lockButton->setIcon(QIcon(":/img/bottom_actions/shutdown.svg")); - lockPalette.setColor(QPalette::Highlight, ShutdownColor); + m_lockButton->setColor(ShutdownColor); break; default: if (m_model->appType() == Login) { @@ -356,9 +377,10 @@ void AuthWidget::setLockButtonType(const int type) } else { m_lockButton->setIcon(DStyle::SP_LockElement); } + // 设置为无效值,自动取活动色 + m_lockButton->setColor(QColor()); break; } - m_lockButton->setPalette(lockPalette); } /** @@ -377,11 +399,13 @@ void AuthWidget::updateBlurEffectGeometry() { QRect rect = this->rect(); rect.setTop(m_userAvatar->geometry().top() + m_userAvatar->height() / 2); - if (m_user->expiredState() == User::ExpiredNormal) { - rect.setBottom(m_lockButton->geometry().top() - 10); + + if (m_user->expiredState() == User::ExpiredNormal && !m_model->terminalLocked()) { + rect.setBottom(m_lockButton->geometry().top() - 20); } else { rect.setBottom(m_expiredStateLabel->geometry().top() - 10); } + m_blurEffectWidget->setGeometry(rect); } @@ -390,25 +414,33 @@ void AuthWidget::updateBlurEffectGeometry() */ void AuthWidget::updatePasswordExpiredState() { + // 锁定情况下不更新密码过期信息 + if (m_model->terminalLocked()) { + return; + } + switch (m_user->expiredState()) { case User::ExpiredNormal: - m_expiredSpacerItem->changeSize(0, 0); m_expiredStateLabel->clear(); m_expiredStateLabel->hide(); break; case User::ExpiredSoon: m_expiredStateLabel->setText(tr("Your password will expire in %n days, please change it timely", "", m_user->expiredDayLeft())); m_expiredStateLabel->show(); - m_expiredSpacerItem->changeSize(0, EXPIRED_SPACER_ITEM_HEIGHT); break; case User::ExpiredAlready: - m_expiredStateLabel->setText(tr("Password expired, please change")); + m_expiredStateLabel->setText(m_user->allowToChangePassword() ? tr("Password expired, please change") : tr("Your password has expired. Please contact the administrator to change it")); m_expiredStateLabel->show(); - m_expiredSpacerItem->changeSize(0, EXPIRED_SPACER_ITEM_HEIGHT); break; default: break; } + if (m_passwordAuth) { + m_passwordAuth->setPasswordLineEditEnabled(m_model->appType() != Login || m_user->allowToChangePassword()); + } + if (m_singleAuth) { + m_singleAuth->setPasswordLineEditEnabled(m_model->appType() != Login || m_user->allowToChangePassword()); + } } /** @@ -418,9 +450,7 @@ void AuthWidget::updatePasswordExpiredState() */ void AuthWidget::registerSyncFunctions(const QString &flag, std::function function) { - if (!m_registerFunctions.contains(flag)) - m_registerFunctions[flag] = m_frameDataBind->registerFunction(flag, function); - m_frameDataBind->refreshData(flag); + } /** @@ -475,7 +505,7 @@ void AuthWidget::syncPassword(const QVariant &value) void AuthWidget::syncPasswordResetPasswordVisibleChanged(const QVariant &value) { if (m_passwordAuth) { - m_passwordAuth->setResetPasswordMessageVisible(value.toBool()); + m_passwordAuth->setResetPasswordMessageVisible(value.toBool(), true); if (m_passwordAuth->isVisible()) m_passwordAuth->updateResetPasswordUI(); } @@ -504,29 +534,59 @@ void AuthWidget::syncUKey(const QVariant &value) m_ukeyAuth->setLineEditInfo(value.toString(), AuthUKey::InputText); } -void AuthWidget::resizeEvent(QResizeEvent *event) -{ - updateBlurEffectGeometry(); - QWidget::resizeEvent(event); -} - void AuthWidget::showEvent(QShowEvent *event) { activateWindow(); + + if (focusProxy()) { + focusProxy()->setFocus(); + } + QWidget::showEvent(event); } int AuthWidget::getTopSpacing() const { const int topHeight = static_cast(topLevelWidget()->geometry().height() * AUTH_WIDGET_TOP_SPACING_PERCENT); - const int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT) - - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN); + const int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN); return qMax(15, deltaY); } +QWidget *AuthWidget::getAuthWidget() +{ + return this; +} + int AuthWidget::calcCurrentHeight(const int height) const { const int h = static_cast(((double) height / (double) BASE_SCREEN_HEIGHT) * topLevelWidget()->geometry().height()); return qMin(h, height); } + +void AuthWidget::terminalLockedChanged(bool locked) +{ + qCInfo(DDE_SHELL) << "AuthWidget terminal locked changed:" << locked; + if (locked) { + m_expiredStateLabel->setText(tr("Terminal locked, please contact administrator")); + m_expiredStateLabel->show(); + m_lockButton->setEnabled(false); + } else { + m_expiredStateLabel->clear(); + m_expiredStateLabel->hide(); + } +} + +void AuthWidget::syncPasswordErrorTipsClearChanged(const QVariant &value) +{ + if (m_passwordAuth ) { + m_passwordAuth->clearPasswrodErrorTip(value.toBool()); + } +} + +void AuthWidget::updatePasswordErrortipUi() +{ + if (m_passwordAuth && m_passwordAuth->canShowPasswrodErrorTip()) { + m_passwordAuth->updatePasswrodErrorTipUi(); + } +} diff --git a/src/session-widgets/auth_widget.h b/src/session-widgets/auth_widget.h index 064cdf7d..47e543f3 100644 --- a/src/session-widgets/auth_widget.h +++ b/src/session-widgets/auth_widget.h @@ -1,36 +1,27 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef AUTHWIDGET_H #define AUTHWIDGET_H #include "userinfo.h" +#include "user_name_widget.h" +#include "transparentbutton.h" +#include "authcommon.h" #include #include #include #include #include +#include +#include #include +#include +#include +#include class AuthSingle; class AuthIris; @@ -39,15 +30,94 @@ class AuthUKey; class AuthFingerprint; class AuthPassword; class AuthCustom; +class AuthPasskey; class DLineEditEx; -class FrameDataBind; -class KbLayoutWidget; class KeyboardMonitor; class SessionBaseModel; class UserAvatar; DWIDGET_USE_NAMESPACE +// 把widget和SpacerItem进行绑定,widget隐藏的时候sapcerItem也隐藏,避免有多余的空白导致布局不符合设计 +class SpacerItemBinder : public QObject, public Dtk::Core::DSingleton +{ + Q_OBJECT + + friend class Dtk::Core::DSingleton; +public: + + void bind(QWidget* w, QSpacerItem* item, QSize size) + { + if (!w || !item) { + return; + } + + connect(w, &QObject::destroyed, this, [w, this] { + m_bindingMap.remove(w); + }); + + auto s = w->isVisible() ? size : QSize(0, 0); + item->changeSize(s.width(), s.height()); + w->installEventFilter(this); + + m_bindingMap.insert(w, qMakePair(item, size)); + } + + bool eventFilter(QObject* watched, QEvent* event) override + { + if ((event->type() == QEvent::Hide || event->type() == QEvent::Show)) { + auto w = qobject_cast(watched); + if (m_bindingMap.contains(w)) { + auto pair = m_bindingMap.value(w); + if (pair.first) { + auto size = event->type() == QEvent::Hide ? QSize(0, 0) : pair.second; + pair.first->changeSize(size.width(), size.height()); + Q_EMIT requestInvalidateLayout(); + } + } + } + + return false; + } + + static void addWidget(QWidget* w, QBoxLayout* layout, Qt::Alignment alignment = Qt::AlignVCenter, int h = 10) + { + QSpacerItem* item = new QSpacerItem(0, h); +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + SpacerItemBinder::instance()->bind(w, item, QSize(0, h)); +#else + SpacerItemBinder::ref().bind(w, item, QSize(0, h)); +#endif + layout->addWidget(w, 0, alignment); + layout->addSpacerItem(item); + } + + void changeItemSize(QWidget* w, QSize size) + { + if (!m_bindingMap.contains(w)) { + return; + } + + auto pair = m_bindingMap.value(w); + if (pair.first) { + pair.first->changeSize(size.width(), size.height()); + pair.second = size; + m_bindingMap[w] = pair; + } + Q_EMIT requestInvalidateLayout(); + } + +Q_SIGNALS: + void requestInvalidateLayout(); + +private: + SpacerItemBinder() = default; + ~SpacerItemBinder() = default; + +private: + QMap> m_bindingMap; +}; + class AuthWidget : public QWidget { Q_OBJECT @@ -57,44 +127,42 @@ class AuthWidget : public QWidget ~AuthWidget() override; virtual void setModel(const SessionBaseModel *model); - virtual void setAuthType(const int type); - virtual void setAuthState(const int type, const int state, const QString &message); + virtual void setAuthType(const AuthCommon::AuthFlags type); + virtual void setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message); virtual int getTopSpacing() const; + virtual QWidget* getAuthWidget(); void setAccountErrorMsg(const QString &message); void syncPasswordResetPasswordVisibleChanged(const QVariant &value); void syncResetPasswordUI(); + void syncPasswordErrorTipsClearChanged(const QVariant &value); + void updatePasswordErrortipUi(); -signals: - void requestCheckAccount(const QString &account); +Q_SIGNALS: + void requestCheckSameNameAccount(const QString &account, bool switchUser = true); + void requestCheckAccount(const QString &account, bool switchUser = true); void requestSetKeyboardType(const QString &key); - void requestStartAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); - void requestEndAuthentication(const QString &account, const int authType); + void requestStartAuthentication(const QString &account, const AuthCommon::AuthFlags authType); + void sendTokenToAuth(const QString &account, const AuthCommon::AuthType authType, const QString &token); + void requestEndAuthentication(const QString &account, const AuthCommon::AuthFlags authType); void authFinished(); void updateParentLayout(); + void noPasswordLoginChanged(const QString &account, bool noPassword); protected: - void resizeEvent(QResizeEvent *event) override; void showEvent(QShowEvent *event) override; protected: void initUI(); void initConnections(); - - virtual void checkAuthResult(const int type, const int state); - + virtual void checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state); void setUser(std::shared_ptr user); void setLimitsInfo(const QMap *limitsInfo); void setAvatar(const QString &avatar); - void updateUserNameLabel(); + void updateUserDisplayNameLabel(); void setPasswordHint(const QString &hint); void setLockButtonType(const int type); - - void updateBlurEffectGeometry(); void updatePasswordExpiredState(); - void updateExpiredState(); - void registerSyncFunctions(const QString &flag, std::function function); void syncSingle(const QVariant &value); void syncSingleResetPasswordVisibleChanged(const QVariant &value); @@ -102,31 +170,32 @@ class AuthWidget : public QWidget void syncPassword(const QVariant &value); void syncUKey(const QVariant &value); int calcCurrentHeight(const int height) const; - int getAuthWidgetHeight(); + void terminalLockedChanged(bool locked); + +protected Q_SLOTS: + void updateBlurEffectGeometry(); + void onNoPasswordLoginChanged(bool noPassword); protected: const SessionBaseModel *m_model; - FrameDataBind *m_frameDataBind; DBlurEffectWidget *m_blurEffectWidget; // 模糊背景 - DFloatingButton *m_lockButton; // 解锁按钮 + TransparentButton *m_lockButton; // 解锁按钮 UserAvatar *m_userAvatar; // 用户头像 DLabel *m_expiredStateLabel; // 密码过期提示 - QSpacerItem *m_expiredSpacerItem; // 密码过期提示与按钮的间隔 - DLabel *m_nameLabel; // 用户名 DLineEditEx *m_accountEdit; // 用户名输入框 - - KeyboardMonitor *m_capslockMonitor; // 大小写 - DClipEffectWidget *m_keyboardTypeClip; // 键盘布局类型菜单边界裁剪类 - - AuthSingle *m_singleAuth; // PAM - AuthPassword *m_passwordAuth; // 密码 - AuthFingerprint *m_fingerprintAuth; // 指纹 - AuthUKey *m_ukeyAuth; // UKey - AuthFace *m_faceAuth; // 面容 - AuthIris *m_irisAuth; // 虹膜 - AuthCustom *m_customAuth; // 自定义认证 + UserNameWidget *m_userNameWidget; // 用户名 + + QPointer m_singleAuth; // PAM + QPointer m_passwordAuth; // 密码 + QPointer m_fingerprintAuth; // 指纹 + QPointer m_ukeyAuth; // UKey + QPointer m_faceAuth; // 面容 + QPointer m_irisAuth; // 虹膜 + QPointer m_passkeyAuth; // 安全密钥 + QPointer m_gestureAuth; // 手势 + QPointer m_customAuth; // 自定义认证 QString m_passwordHint; // 密码提示 QString m_keyboardType; // 键盘布局类型 @@ -136,6 +205,9 @@ class AuthWidget : public QWidget QList m_connectionList; QMap m_registerFunctions; + + QTimer *m_refreshTimer; + AuthCommon::AuthState m_authState; // 当前验证状态 }; #endif // AUTHWIDGET_H diff --git a/src/session-widgets/authinterface.cpp b/src/session-widgets/authinterface.cpp index b5501048..72a530be 100644 --- a/src/session-widgets/authinterface.cpp +++ b/src/session-widgets/authinterface.cpp @@ -1,12 +1,14 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "authinterface.h" #include "sessionbasemodel.h" #include "userinfo.h" +#include "dbusconstant.h" -#include -#include -#include -#include #include +#include #define POWER_CAN_SLEEP "POWER_CAN_SLEEP" #define POWER_CAN_HIBERNATE "POWER_CAN_HIBERNATE" @@ -16,22 +18,33 @@ using namespace Auth; AuthInterface::AuthInterface(SessionBaseModel *const model, QObject *parent) : QObject(parent) , m_model(model) - , m_accountsInter(new AccountsInter("com.deepin.daemon.Accounts", "/com/deepin/daemon/Accounts", QDBusConnection::systemBus(), this)) - , m_loginedInter(new LoginedInter("com.deepin.daemon.Accounts", "/com/deepin/daemon/Logined", QDBusConnection::systemBus(), this)) + , m_accountsInter(new AccountsInter(DSS_DBUS::accountsService, DSS_DBUS::accountsPath, QDBusConnection::systemBus(), this)) + , m_loginedInter(new LoginedInter(DSS_DBUS::accountsService, DSS_DBUS::loginedPath, QDBusConnection::systemBus(), this)) , m_login1Inter(new DBusLogin1Manager("org.freedesktop.login1", "/org/freedesktop/login1", QDBusConnection::systemBus(), this)) - , m_powerManagerInter(new PowerManagerInter("com.deepin.daemon.PowerManager", "/com/deepin/daemon/PowerManager", QDBusConnection::systemBus(), this)) - , m_authenticateInter(new Authenticate("com.deepin.daemon.Authenticate", "/com/deepin/daemon/Authenticate", QDBusConnection::systemBus(), this)) , m_dbusInter(new DBusObjectInter("org.freedesktop.DBus", "/org/freedesktop/DBus", QDBusConnection::systemBus(), this)) , m_lastLogoutUid(0) , m_currentUserUid(0) , m_loginUserList(0) + , m_isVM(detectVirtualMachine()) { +#ifndef ENABLE_DSS_SNIPE + // 需要先初始化m_gsettings + if (QGSettings::isSchemaInstalled("com.deepin.dde.session-shell")) { + m_gsettings = new QGSettings("com.deepin.dde.session-shell", "/com/deepin/dde/session-shell/", this); + } +#else + if (!m_dConfig) { + m_dConfig = Dtk::Core::DConfig::create("org.deepin.dde.session-shell", "org.deepin.dde.session-shell", QString(), this); + } +#endif + + if (m_login1Inter->isValid()) { QString session_self = m_login1Inter->GetSessionByPID(0).value().path(); m_login1SessionSelf = new Login1SessionSelf("org.freedesktop.login1", session_self, QDBusConnection::systemBus(), this); m_login1SessionSelf->setSync(false); } else { - qWarning() << "m_login1Inter:" << m_login1Inter->lastError().type(); + qCWarning(DDE_SHELL) << "Login interface is invalid, error:" << m_login1Inter->lastError().type(); } } @@ -47,7 +60,7 @@ void AuthInterface::onUserListChanged(const QStringList &list) QStringList tmpList; for (std::shared_ptr u : m_model->userList()) { if (u->type() == User::Native) - tmpList << ACCOUNTS_DBUS_PREFIX + QString::number(u->uid()); + tmpList << QString(DSS_DBUS::accountsUserPath).arg(QString::number(u->uid())); } for (const QString &u : list) { @@ -88,7 +101,6 @@ void AuthInterface::onUserRemove(const QString &user) void AuthInterface::initData() { onUserListChanged(m_accountsInter->userList()); - onLastLogoutUserChanged(m_loginedInter->lastLogoutUser()); onLoginUserListChanged(m_loginedInter->userList()); // m_accountsInter->userList(); // m_loginedInter->lastLogoutUser(); @@ -106,25 +118,9 @@ void AuthInterface::initDBus() connect(m_accountsInter, &AccountsInter::UserAdded, this, &AuthInterface::onUserAdded, Qt::QueuedConnection); connect(m_accountsInter, &AccountsInter::UserDeleted, this, &AuthInterface::onUserRemove, Qt::QueuedConnection); - connect(m_loginedInter, &LoginedInter::LastLogoutUserChanged, this, &AuthInterface::onLastLogoutUserChanged); connect(m_loginedInter, &LoginedInter::UserListChanged, this, &AuthInterface::onLoginUserListChanged); } -void AuthInterface::onLastLogoutUserChanged(uint uid) -{ - m_lastLogoutUid = uid; - - QList> userList = m_model->userList(); - for (auto it = userList.constBegin(); it != userList.constEnd(); ++it) { - if ((*it)->uid() == uid) { - m_model->updateLastLogoutUser((*it)); - return; - } - } - - m_model->updateLastLogoutUser(std::shared_ptr(nullptr)); -} - void AuthInterface::onLoginUserListChanged(const QString &list) { m_loginUserList.clear(); @@ -145,10 +141,10 @@ void AuthInterface::onLoginUserListChanged(const QString &list) auto find_it = std::find_if( availableUidList.begin(), availableUidList.end(), - [=] (const uint find_addomain_uid) { return find_addomain_uid == uid; }); + [=](const uint find_adDomain_uid) { return find_adDomain_uid == uid; }); if (haveDisplay && find_it == availableUidList.end()) { - // init addoman user + // init adDomain user std::shared_ptr u(new ADDomainUser(uid)); u->updateLoginState(true); @@ -187,6 +183,7 @@ bool AuthInterface::checkHaveDisplay(const QJsonArray &array) return false; } +#ifndef ENABLE_DSS_SNIPE QVariant AuthInterface::getGSettings(const QString& node, const QString& key) { QVariant value = valueByQSettings(node, key, true); @@ -195,6 +192,16 @@ QVariant AuthInterface::getGSettings(const QString& node, const QString& key) } return value; } +#else +QVariant AuthInterface::getDconfigValue(const QString &key, const QVariant &fallbackValue) +{ + if (m_dConfig) { + return m_dConfig->value(key, fallbackValue); + } + + return fallbackValue; +} +#endif bool AuthInterface::isLogined(uint uid) { @@ -208,26 +215,86 @@ bool AuthInterface::isDeepin() #ifdef QT_DEBUG return true; #else + +#ifndef ENABLE_DSS_SNIPE return getGSettings("","useDeepinAuth").toBool(); +#else + return getDconfigValue("useDeepinAuth", true).toBool(); +#endif + #endif } void AuthInterface::checkConfig() { +#ifndef ENABLE_DSS_SNIPE m_model->setAlwaysShowUserSwitchButton(getGSettings("","switchuser").toInt() == AuthInterface::Always); m_model->setAllowShowUserSwitchButton(getGSettings("","switchuser").toInt() == AuthInterface::Ondemand); +#else + m_model->setAlwaysShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Always); + m_model->setAllowShowUserSwitchButton(getDconfigValue("switchUser", Ondemand).toInt() == AuthInterface::Ondemand); +#endif } void AuthInterface::checkPowerInfo() { - //替换接口org.freedesktop.login1 为com.deepin.sessionManager,原接口的是否支持待机和休眠的信息不准确 + // 替换接口org.freedesktop.login1 为com.deepin.sessionManager,原接口的是否支持待机和休眠的信息不准确 QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - bool can_sleep = env.contains(POWER_CAN_SLEEP) ? QVariant(env.value(POWER_CAN_SLEEP)).toBool() - : getGSettings("Power","sleep").toBool() && m_powerManagerInter->CanSuspend(); +#ifndef ENABLE_DSS_SNIPE + bool can_sleep = getGSettings("Power","sleep").toBool() && canSuspend(); + bool can_hibernate = getGSettings("Power","hibernate").toBool() && canHibernate(); +#else + bool can_sleep = getDconfigValue("sleep", true).toBool() && canSuspend(); + bool can_hibernate = getDconfigValue("hibernate", true).toBool() && canHibernate(); +#endif + m_model->setCanSleep(can_sleep); + m_model->setHasSwap(can_hibernate); +} - bool can_hibernate = env.contains(POWER_CAN_HIBERNATE) ? QVariant(env.value(POWER_CAN_HIBERNATE)).toBool() - : getGSettings("Power","hibernate").toBool() && m_powerManagerInter->CanHibernate(); +bool AuthInterface::checkIsADDomain() +{ + //只有加入AD域后,才会生成此文件 + return QFile::exists("/etc/krb5.keytab"); +} - m_model->setHasSwap(can_hibernate); +bool AuthInterface::canSuspend() +{ + if (QString(getenv("POWER_CAN_SLEEP")) == "0" || m_isVM) + return false; + + // 检查内存休眠支持文件是否存在 + if (!QFile::exists("/sys/power/mem_sleep")) + return false; + + QString canSuspend = m_login1Inter->CanSuspend(); + return canSuspend == "yes"; +} + +bool AuthInterface::canHibernate() +{ + if (QString(getenv("POWER_CAN_HIBERNATE")) == "0" || m_isVM) + return false; + + QString canHibernate = m_login1Inter->CanHibernate(); + return canHibernate == "yes"; } + +bool AuthInterface::detectVirtualMachine() +{ + QProcess process; + process.start("/usr/bin/systemd-detect-virt", QStringList()); + // 添加超时限制,例如 3000ms + if (!process.waitForFinished(3000)) { + qWarning() << "Timeout detecting virtual machine"; + return false; + } + + if (process.exitCode() != 0) { + qWarning() << "Failed to detect virtual machine, error:" << process.errorString(); + return false; + } + + QString name = QString::fromUtf8(process.readAllStandardOutput()).trimmed(); + return name != "none" && !name.isEmpty(); +} \ No newline at end of file diff --git a/src/session-widgets/authinterface.h b/src/session-widgets/authinterface.h index 9b62474c..f9472bf6 100644 --- a/src/session-widgets/authinterface.h +++ b/src/session-widgets/authinterface.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef AUTHINTERFACE_H #define AUTHINTERFACE_H @@ -5,25 +9,40 @@ #include "constants.h" #include "dbuslogin1manager.h" +#ifndef ENABLE_DSS_SNIPE #include #include #include #include -#include #include +#include +#else +#include "authenticate1interface.h" +#include "accounts1interface.h" +#include "loginedinterface.h" +#include "dbusinterface.h" +#include "selfinterface.h" +#include +#endif -#include #include -#include #include +#ifndef ENABLE_DSS_SNIPE using AccountsInter = com::deepin::daemon::Accounts; using LoginedInter = com::deepin::daemon::Logined; using Login1SessionSelf = org::freedesktop::login1::Session; -using PowerManagerInter = com::deepin::daemon::PowerManager; using DBusObjectInter = org::freedesktop::DBus; using com::deepin::daemon::Authenticate; +#else +using AccountsInter = org::deepin::dde::Accounts1; +using LoginedInter = org::deepin::dde::Logined; +using Login1SessionSelf = org::freedesktop::login1::Session; +using DBusObjectInter = org::freedesktop::DBus; + +using Authenticate = org::deepin::dde::Authenticate1; +#endif class User; class SessionBaseModel; @@ -50,16 +69,19 @@ class AuthInterface : public QObject { protected: void initDBus(); void initData(); - void onLastLogoutUserChanged(uint uid); void onLoginUserListChanged(const QString &list); bool checkHaveDisplay(const QJsonArray &array); bool isLogined(uint uid); void checkConfig(); void checkPowerInfo(); + bool checkIsADDomain(); bool isDeepin(); +#ifndef ENABLE_DSS_SNIPE QVariant getGSettings(const QString& node, const QString& key); - +#else + QVariant getDconfigValue(const QString &key, const QVariant &fallbackValue); +#endif template T valueByQSettings(const QString & group, const QString & key, @@ -70,19 +92,26 @@ class AuthInterface : public QObject { failback); } + bool canSuspend(); + bool canHibernate(); + bool detectVirtualMachine(); + protected: SessionBaseModel* m_model; AccountsInter * m_accountsInter; LoginedInter* m_loginedInter; DBusLogin1Manager* m_login1Inter; Login1SessionSelf* m_login1SessionSelf = nullptr; - PowerManagerInter* m_powerManagerInter; - Authenticate* m_authenticateInter; DBusObjectInter* m_dbusInter; +#ifndef ENABLE_DSS_SNIPE QGSettings* m_gsettings = nullptr; +#else + Dtk::Core::DConfig* m_dConfig = nullptr; +#endif uint m_lastLogoutUid; uint m_currentUserUid; std::list m_loginUserList; + bool m_isVM; }; } // namespace Auth diff --git a/src/session-widgets/buttonbox.cpp b/src/session-widgets/buttonbox.cpp new file mode 100644 index 00000000..a56342f6 --- /dev/null +++ b/src/session-widgets/buttonbox.cpp @@ -0,0 +1,195 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "buttonbox.h" + +#include +#include + +#include +#include +#include +#include + +const int IconSize = 26; +const int Radius = 10; + +ButtonBoxButton::ButtonBoxButton(const QIcon& icon, const QString &text, QWidget *parent) + : QAbstractButton(parent) + , m_radius(0) + , m_leftRoundEnabled(false) + , m_rightRoundEnabled(false) + , m_visible(true) +{ + QAbstractButton::setIcon(icon); + QAbstractButton::setText(text); +} + +ButtonBoxButton::ButtonBoxButton(DStyle::StandardPixmap iconType, const QString &text, QWidget *parent) + :QAbstractButton (parent) +{ + QAbstractButton::setIcon(DStyleHelper(style()).standardIcon(iconType, nullptr, this)); + QAbstractButton::setText(text); +} + +void ButtonBoxButton::setIcon(const QIcon &icon) +{ + QAbstractButton::setIcon(icon); +} + +void ButtonBoxButton::setIcon(DStyle::StandardPixmap iconType) +{ + QAbstractButton::setIcon(DStyleHelper(style()).standardIcon(iconType, nullptr, this)); +} + +void ButtonBoxButton::setRadius(int radius) +{ + m_radius = radius; + update(); +} + +void ButtonBoxButton::setLeftRoundedEnabled(bool enabled) +{ + if (m_leftRoundEnabled == enabled) + return; + + m_leftRoundEnabled = enabled; + update(); +} + +void ButtonBoxButton::setRightRoundedEnabled(bool enabled) +{ + if (m_rightRoundEnabled == enabled) + return; + + m_rightRoundEnabled = enabled; + update(); +} + +void ButtonBoxButton::paintEvent(QPaintEvent *event) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + p.setPen(Qt::NoPen); + QColor color = this->palette().color(QPalette::Button); + + p.setClipping(true); + + QPainterPath path; + if (m_leftRoundEnabled || m_rightRoundEnabled) { + + // 先绘制圆角矩形 + path.addRoundedRect(rect(), m_radius, m_radius); + if (m_leftRoundEnabled) { + + // 填充矩形右边两个角的圆角 + path.addRect(width() - m_radius, 0, m_radius, m_radius); // 填充右上角 + path.addRect(width() - m_radius, height() - m_radius, m_radius, m_radius); // 填充右下角 + } else { + + // 填充矩形左边两个角的圆角 + path.addRect(0, height() - m_radius, m_radius, m_radius); // 填充左上角 + path.addRect(0, 0, m_radius, m_radius); // 填充左下角 + } + } else { + path.addRect(rect()); + } + path.setFillRule(Qt::WindingFill); + + p.setClipPath(path); + + QStyleOption opt; + opt.initFrom(this); + if (opt.state & QStyle::StateFlag::State_MouseOver) { + color.setAlphaF(0.1); + p.setBrush(color); + } + + if (isChecked()) { + p.setBrush(this->palette().highlight()); + } + + p.drawRect(this->rect()); + p.setClipping(false); + + //绘制图标 + int x = this->rect().x() + rect().width() / 2 - IconSize / 2; + int y = this->rect().y() + rect().height() / 2 - IconSize / 2; + p.drawPixmap(x, y, icon().pixmap(IconSize, IconSize)); + QWidget::paintEvent(event); +} + +//ButtonBox类 +ButtonBox::ButtonBox(QWidget *parent) + : QWidget(parent) + , m_group(new QButtonGroup(this)) + , m_layout(new QHBoxLayout(this)) + , m_atCustonBtnHide(false) +{ + m_layout->setContentsMargins(0, 0, 0, 0); +} + +void ButtonBox::setButtonList(const QList &list, bool checkable) +{ + if(list.isEmpty()) + return; + + for (QAbstractButton *button : m_group->buttons()) { + m_group->removeButton(button); + m_layout->removeWidget(button); + } + + ButtonBoxButton *lastVisibleButton = list.first(); + for (int i = 0; i < list.count(); ++i) { + ButtonBoxButton *button = list.at(i); + if (!button) + continue; + + button->setLeftRoundedEnabled(false); + button->setRightRoundedEnabled(false); + button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + m_layout->addWidget(button); + m_layout->setSpacing(0); + m_group->addButton(button); + button->setCheckable(checkable); + if (button->testVisibleAttr()) + lastVisibleButton = button; + } + + list.first()->setLeftRoundedEnabled(true); + list.first()->setRadius(Radius); + + if (lastVisibleButton) { + lastVisibleButton->setRightRoundedEnabled(true); + lastVisibleButton->setRadius(Radius); + } +} + +void ButtonBox::removeButton(ButtonBoxButton* button) +{ + if (!button) + return; + m_group->removeButton(button); + m_layout->removeWidget(button); +} + +void ButtonBox::paintEvent(QPaintEvent *event) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(palette().color(QPalette::Button)); + p.setPen(Qt::NoPen); + p.drawRoundedRect(this->rect(), Radius, Radius); + QWidget::paintEvent(event); +} + +QList ButtonBox::buttonBoxList() const +{ + QList list; + for (const auto &btn : m_group->buttons()) { + if (const auto bbtn = dynamic_cast(btn)) + list.append(bbtn); + } + return list; +} diff --git a/src/session-widgets/buttonbox.h b/src/session-widgets/buttonbox.h new file mode 100644 index 00000000..9dced6ee --- /dev/null +++ b/src/session-widgets/buttonbox.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef BUTTONBOX_H +#define BUTTONBOX_H + +#include + +#include +#include + +DWIDGET_USE_NAMESPACE +class QHBoxLayout; +class ButtonBoxButton : public QAbstractButton +{ + Q_OBJECT +public: + ButtonBoxButton(const QIcon& icon, const QString &text = QString(), QWidget *parent = nullptr); + ButtonBoxButton(DStyle::StandardPixmap iconType = static_cast(-1), + const QString &text = QString(), QWidget *parent = nullptr); + + void setIcon(const QIcon &icon); + void setIcon(DStyle::StandardPixmap iconType); + void setRadius(int radius); + void setLeftRoundedEnabled(bool enabled); + void setRightRoundedEnabled(bool enabled); + void setVisibleAttr(bool visible) { m_visible = visible; } + inline bool testVisibleAttr() const { return m_visible; } + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + int m_radius; + bool m_leftRoundEnabled; + bool m_rightRoundEnabled; + bool m_visible; // 标识 button 是否需要显示 +}; + +//ButtonBox类 +class ButtonBox : public QWidget +{ + Q_OBJECT +public: + ButtonBox(QWidget *parent = nullptr); + + void setButtonList(const QList &list, bool checkable); + inline QList buttonList() const { return m_group->buttons(); } + void removeButton(ButtonBoxButton* button); + QList buttonBoxList() const; + inline QAbstractButton *checkedButton() const { return m_group->checkedButton(); } + inline QAbstractButton *button(int id) const { return m_group->button(id); } + inline void setId(QAbstractButton *button, int id) { m_group->setId(button, id); } + inline int checkedId() const { return m_group->checkedId(); } + inline void setATCustomBtnHide(bool btnHide) { m_atCustonBtnHide = btnHide; } + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QButtonGroup *m_group; + QHBoxLayout *m_layout; + bool m_atCustonBtnHide; +}; +#endif // BUTTONBOX_H diff --git a/src/session-widgets/framedatabind.cpp b/src/session-widgets/framedatabind.cpp deleted file mode 100644 index d914cb0f..00000000 --- a/src/session-widgets/framedatabind.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2018 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: fanpengcheng - * - * Maintainer: fanpengcheng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "framedatabind.h" - -FrameDataBind::FrameDataBind() - : QObject() -{ - -} - -FrameDataBind::~FrameDataBind() -{ - -} - -FrameDataBind *FrameDataBind::Instance() -{ - static FrameDataBind frameDataBind; - return &frameDataBind; -} - -int FrameDataBind::registerFunction(const QString &flag, std::function function) -{ - for (auto it = m_registerList.begin(); it != m_registerList.end(); ++it) { - if (it.key() == flag) { - QList keys = it.value().keys(); - int index = 0; - while (true) { - if (!keys.contains(index)) { - it.value()[index] = function; - return index; - } - - ++index; - } - } - } - - m_registerList[flag][0] = function; - return 0; -} - -void FrameDataBind::unRegisterFunction(const QString &flag, int index) -{ - for (auto it = m_registerList.begin(); it != m_registerList.end(); ++it) { - if (it.key() == flag) { - it.value().remove(index); - } - } -} - -QVariant FrameDataBind::getValue(const QString &flag) const -{ - if (m_datas.contains(flag)) { - return m_datas[flag]; - } else { - return QVariant(); - } -} - -void FrameDataBind::updateValue(const QString &flag, const QVariant &value) -{ - m_datas[flag] = value; - - refreshData(flag); -} - -void FrameDataBind::clearValue(const QString &flag) -{ - if (m_datas.contains(flag)) { - m_datas.remove(flag); - } -} - -void FrameDataBind::refreshData(const QString &flag) -{ - QList> functions = m_registerList[flag].values(); - - for (auto it = functions.constBegin(); it != functions.constEnd(); ++it) { - (*it)(m_datas[flag]); - } -} diff --git a/src/session-widgets/framedatabind.h b/src/session-widgets/framedatabind.h deleted file mode 100644 index acb08d79..00000000 --- a/src/session-widgets/framedatabind.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2018 ~ 2021 Uniontech Technology Co., Ltd. - * - * Author: fanpengcheng - * - * Maintainer: fanpengcheng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef FRAMEDATABIND_H -#define FRAMEDATABIND_H - -#include -#include -#include - -class FrameDataBind : public QObject -{ - Q_OBJECT -public: - static FrameDataBind *Instance(); - - int registerFunction(const QString &flag, std::function function); - void unRegisterFunction(const QString &flag, int index); - - QVariant getValue(const QString &flag) const; - void updateValue(const QString &flag, const QVariant &value); - void clearValue(const QString &flag); - - void refreshData(const QString &flag); - -private: - FrameDataBind(); - ~FrameDataBind() override; - FrameDataBind(const FrameDataBind &) = delete; - -private: - QMap>> m_registerList; - QMap m_datas; -}; - -#endif // FRAMEDATABIND_H diff --git a/src/session-widgets/fullmanagedauthwidget.cpp b/src/session-widgets/fullmanagedauthwidget.cpp new file mode 100644 index 00000000..0967f57a --- /dev/null +++ b/src/session-widgets/fullmanagedauthwidget.cpp @@ -0,0 +1,267 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "fullmanagedauthwidget.h" + +#include "auth_custom.h" +#include "authcommon.h" +#include "dlineeditex.h" +#include "keyboardmonitor.h" +#include "modules_loader.h" +#include "sessionbasemodel.h" +#include "useravatar.h" +#include "plugin_manager.h" + +QList FullManagedAuthWidget::FullManagedAuthWidgetObjs = {}; +FullManagedAuthWidget::FullManagedAuthWidget(QWidget *parent) + : AuthWidget(parent) + , m_mainLayout(new QVBoxLayout(this)) + , m_currentAuthType(AT_All) + , m_inited(false) + , m_isPluginLoaded(false) +{ + setObjectName(QStringLiteral("FullManagedAuthWidget")); + setAccessibleName(QStringLiteral("FullManagedAuthWidget")); + + FullManagedAuthWidgetObjs.append(this); +} + +FullManagedAuthWidget::~FullManagedAuthWidget() +{ + FullManagedAuthWidgetObjs.removeAll(this); +} + +void FullManagedAuthWidget::hideInternalControls() +{ + auto hide = [](QWidget *wid) { + if (wid) { + wid->setVisible(false); + wid->setDisabled(true); + } + }; + + hide(m_accountEdit); + hide(m_userNameWidget); + hide(m_userAvatar); + hide(m_lockButton); +} + +void FullManagedAuthWidget::initUI() +{ + AuthWidget::initUI(); +} + +void FullManagedAuthWidget::initConnections() +{ + AuthWidget::initConnections(); + connect(m_model, &SessionBaseModel::authTypeChanged, this, &FullManagedAuthWidget::setAuthType); + connect(m_model, &SessionBaseModel::authStateChanged, this, &FullManagedAuthWidget::setAuthState); +} + +void FullManagedAuthWidget::setModel(const SessionBaseModel *model) +{ + AuthWidget::setModel(model); + + initUI(); + initConnections(); + + // 在登陆设置验证类型的时候需要判断当前是否是"..."账户,需要先设置当前用户,在设置验证类型,两者的顺序切勿颠倒。 + setUser(model->currentUser()); + setAuthType(model->getAuthProperty().AuthType); + hideInternalControls(); + + m_inited = true; +} + +void FullManagedAuthWidget::setAuthType(const AuthFlags type) +{ + int authType = type; + LoginPlugin *plugin = PluginManager::instance()->getFullManagedLoginPlugin(); + if (plugin + && !m_model->currentUser()->isNoPasswordLogin() + && !m_model->currentUser()->isAutomaticLogin()) { + authType |= AT_Custom; + initCustomAuth(); + + // 只有当首次创建sfa或者这个对象已经初始化过了才应用DefaultAuthLevel + // 这是只是一个规避方案,主要是因为每个屏幕都会创建一个sfa,这看起来不太合理,特别是处理单例对象时,带来很大的不便。 + + // TODO 每个屏幕只创建一个LockContent,鼠标在屏幕间移动的时候重新设置LockContent的parent即可。 + qCInfo(DDE_SHELL) << "FMA is inited: " << m_inited << ", FMA widgets size: " << FullManagedAuthWidgetObjs.size(); + if (m_inited || FullManagedAuthWidgetObjs.size() <= 1) { + if (m_customAuth->pluginConfig().defaultAuthLevel == LoginPlugin::DefaultAuthLevel::Default) { + m_currentAuthType = m_currentAuthType == AT_All ? AT_Custom : m_currentAuthType; + } else if (m_customAuth->pluginConfig().defaultAuthLevel == LoginPlugin::DefaultAuthLevel::StrongDefault) { + m_currentAuthType = AT_Custom; + } + } + } else if (m_customAuth) { + delete m_customAuth; + m_customAuth = nullptr; + } + + if (m_inited && m_customAuth) + Q_EMIT requestStartAuthentication(m_model->currentUser()->name(), AT_Custom); +} + +void FullManagedAuthWidget::setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) +{ + qCDebug(DDE_SHELL) << "Set auth state, type: " << type << ", state: " << state << ", message: " << message; + if (!isPluginLoaded()) { + qCDebug(DDE_SHELL) << "Plugin not load or actived"; + return; + } + + if (!m_customAuth) { + qCDebug(DDE_SHELL) << Q_FUNC_INFO << "custom auth not init"; + return; + } + + switch (type) { + case AT_PAM: + case AT_Custom: + // 根据早期设计,自定义的插件需要通过lightdmAuthStarted方法通知插件,然后插件send token回来 + // 插件侧需要处理命名为"StartAuth"的交互请求 + if (state == AS_Prompt && m_model->appType() == AuthCommon::AppType::Login) { + m_customAuth->lightdmAuthStarted(); + break; + } + + m_customAuth->setAuthState(state, message); + break; + case AT_All: + checkAuthResult(AT_All, state); + break; + default: + break; + } + + // 同步验证状态给插件 + if (m_customAuth) { + m_customAuth->notifyAuthState(type, state); + } +} + +void FullManagedAuthWidget::initCustomAuth() +{ + qCDebug(DDE_SHELL) << "Init custom auth"; + if (m_customAuth) { + return; + } + + auto plugin = PluginManager::instance()->getFullManagedLoginPlugin(); + if (!plugin) { + qCDebug(DDE_SHELL) << "No full managed plugin found"; + return; + } + + m_customAuth = new AuthCustom(this); + m_customAuth->setModule(plugin); + m_customAuth->setModel(m_model); + m_customAuth->initUi(); + m_customAuth->show(); + m_mainLayout->addWidget(m_customAuth); + + setLayout(m_mainLayout); + + connect(m_customAuth, &AuthCustom::requestSendToken, this, [this](const QString &token) { + qCInfo(DDE_SHELL) << "Fma custom send token name :" << m_user->name(); + Q_EMIT sendTokenToAuth(m_user->name(), AT_Custom, token); + }); + + connect(m_customAuth, &AuthCustom::requestCheckAccount, this, [this](const QString &account) { + qCInfo(DDE_SHELL) << "Request check account: " << account; + + if (account.isEmpty()) { + qCInfo(DDE_SHELL) << "Account is empty" << account; + return; + } + + + // 用户不一致时切换用户 + if (m_user->name() != account) { + // 切换用户 + Q_EMIT requestCheckAccount(account); + } else { + qCDebug(DDE_SHELL) << "Start to send token"; + LoginPlugin::AuthCallbackData data = m_customAuth->getCurrentAuthData(); + if (data.result == LoginPlugin::AuthResult::Success) { + Q_EMIT sendTokenToAuth(m_user->name(), AT_Custom, data.token); + } else { + qCWarning(DDE_SHELL) << "Token auth failed , result: " << data.result; + } + } + }); + + connect(m_customAuth, &AuthCustom::notifyAuthTypeChange, this, &FullManagedAuthWidget::onRequestChangeAuth); + m_isPluginLoaded = true; +} + +void FullManagedAuthWidget::checkAuthResult(const AuthType type, const AuthState state) +{ + // 等所有类型验证通过的时候在发送验证完成信息,否则DA的验证结果可能还没有刷新,导致lightdm调用pam验证失败 + // 人脸和虹膜是手动点击解锁按钮后发送,无需处理 + if (type == AT_All && state == AS_Success) { + if (m_customAuth && m_customAuth->authState() == AS_Success) { + emit authFinished(); + } + + if (m_customAuth) { + m_customAuth->resetAuth(); + m_customAuth->reset(); + } + } +} + +void FullManagedAuthWidget::resizeEvent(QResizeEvent *event) +{ + updateBlurEffectGeometry(); + + AuthWidget::resizeEvent(event); +} + +void FullManagedAuthWidget::showEvent(QShowEvent *event) +{ + // fullmanaged plugin start auth on UI button clicked + Q_EMIT requestStartAuthentication(m_user->name(), AT_Custom); + AuthWidget::showEvent(event); +} + +// plugin do not neet to response auth changing +void FullManagedAuthWidget::onRequestChangeAuth(const AuthType authType) +{ + Q_UNUSED(authType); +} + +bool FullManagedAuthWidget::isPluginLoaded() const +{ + if (!m_customAuth) { + return false; + } + + auto plugin = m_customAuth->getLoginPlugin(); + if (!plugin) { + return false; + } + + return m_isPluginLoaded && plugin->isPluginEnabled(); +} + +bool FullManagedAuthWidget::isUserSwitchButtonVisiable() const +{ + // get config from plugin + do { + if(!isPluginLoaded()){ + break; + } + + auto plugin = m_customAuth->getLoginPlugin(); + if (!plugin) { + break; + } + + return plugin->pluginConfig().showSwitchButton; + } while(false); + + return PluginConfig::isUserSwitchButtonVisiable(); +} diff --git a/src/session-widgets/fullmanagedauthwidget.h b/src/session-widgets/fullmanagedauthwidget.h new file mode 100644 index 00000000..269a24ec --- /dev/null +++ b/src/session-widgets/fullmanagedauthwidget.h @@ -0,0 +1,59 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef FULLMANAGEDAUTHWIDGET_H +#define FULLMANAGEDAUTHWIDGET_H + +#include "auth_widget.h" +#include "userinfo.h" +#include "authcommon.h" +#include "pluginconfigmap.h" + +class AuthModule; +class KbLayoutWidget; +class KeyboardMonitor; + +namespace dss { +namespace module { +class LoginModuleInterface; +}; +}; // namespace dss + +class FullManagedAuthWidget : public AuthWidget + , public PluginConfig +{ + Q_OBJECT +public: + explicit FullManagedAuthWidget(QWidget *parent = nullptr); + ~FullManagedAuthWidget() override; + + void setModel(const SessionBaseModel *model) override; + void setAuthType(const AuthCommon::AuthFlags type) override; + void setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) override; + bool isPluginLoaded() const; + virtual bool isUserSwitchButtonVisiable() const override; + +public slots: + void onRequestChangeAuth(const AuthCommon::AuthType authType); + +protected: + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; + +private: + void initUI(); + void hideInternalControls(); + void initConnections(); + void initCustomAuth(); + void checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state) override; + +private: + QVBoxLayout *m_mainLayout; + AuthCommon::AuthType m_currentAuthType; + static QList FullManagedAuthWidgetObjs; + bool m_inited; + bool m_isPluginLoaded; +}; + +#endif // FULLMANAGEDAUTHWIDGET_H diff --git a/src/session-widgets/lockcontent.cpp b/src/session-widgets/lockcontent.cpp index 33dd4d48..4a6fde8e 100644 --- a/src/session-widgets/lockcontent.cpp +++ b/src/session-widgets/lockcontent.cpp @@ -1,75 +1,124 @@ +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "lockcontent.h" -#include "base_module_interface.h" #include "controlwidget.h" #include "logowidget.h" #include "mfa_widget.h" -#include "modules_loader.h" +#include "popupwindow.h" #include "sessionbasemodel.h" #include "sfa_widget.h" #include "shutdownwidget.h" -#include "timewidget.h" #include "userframelist.h" #include "virtualkbinstance.h" +#include "plugin_manager.h" +#include "fullmanagedauthwidget.h" +#include "keyboardmonitor.h" +#include "dconfig_helper.h" +#include "constants.h" +#include "mfasequencecontrol.h" #include +#include #include #include +#include "dbusconstant.h" + using namespace dss; using namespace dss::module; +DCORE_USE_NAMESPACE -LockContent::LockContent(SessionBaseModel *const model, QWidget *parent) +LockContent::LockContent(QWidget *parent) : SessionBaseWindow(parent) - , m_model(model) - , m_virtualKB(nullptr) , m_wmInter(new com::deepin::wm("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this)) - , m_sfaWidget(nullptr) - , m_mfaWidget(nullptr) - , m_authWidget(nullptr) - , m_userListWidget(nullptr) , m_localServer(new QLocalServer(this)) + , m_currentModeStatus(SessionBaseModel::ModeStatus::NoStatus) + , m_showMediaWidget(DConfigHelper::instance()->getConfig(SHOW_MEDIA_WIDGET, false).toBool()) { - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + +} + +LockContent *LockContent::instance() +{ + static LockContent *lockContent = nullptr; + if (!lockContent) { + lockContent = new LockContent(); + } + + return lockContent; +} + +void LockContent::init(SessionBaseModel *model) +{ + if (m_initialized) { + qCWarning(DDE_SHELL) << "Has been initialized, don't do it again"; + return; + } + m_initialized = true; + m_model = model; + // 异步获取CPU硬件信息,判断是否为PANGU CPU + // FIXME: CPU硬件信息可能会改且其它的机型也可能会有PANGU CPU,这里的判断不准确 + if (m_model->appType() == AuthCommon::Lock) { + QDBusInterface interface(DSS_DBUS::systemInfoService, + DSS_DBUS::systemInfoPath, + "org.freedesktop.DBus.Properties", + QDBusConnection::sessionBus(), + this); + QDBusPendingReply reply = interface.asyncCall("Get", DSS_DBUS::systemInfoService, "CPUHardware"); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher] { + QDBusPendingReply reply = *watcher; + if (reply.isValid()) { + QString cpuHardware = reply.value().variant().toString(); + qCInfo(DDE_SHELL) << "Current cpu hardware:" << cpuHardware; + if (cpuHardware.contains("PANGU")) { + m_isPANGUCpu = true; + } + } else { + qCWarning(DDE_SHELL) << "Failed to get CPU hardware:" << reply.error().message(); + } + watcher->deleteLater(); + }); + } + // 在已显示关机或用户列表界面时,再插入另外一个显示器,会新构建一个LockContent,此时会设置为PasswordMode造成界面状态异常 + if (!m_model->visible()) { + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + } initUI(); initConnections(); - if (model->appType() == Lock) { + if (model->appType() == AuthCommon::Lock) { setMPRISEnable(model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode); } - QTimer::singleShot(0, this, [=] { - onCurrentUserChanged(model->currentUser()); - onUserListChanged(model->isServerModel() ? model->loginedUserList() : model->userList()); + QTimer::singleShot(0, this, [this] { + onCurrentUserChanged(m_model->currentUser()); }); + // 创建套接字连接,用于与重置密码弹窗通讯 m_localServer->setMaxPendingConnections(1); m_localServer->setSocketOptions(QLocalServer::WorldAccessOption); - static bool once = false; - if (!once) { - // 将greeter和lock的服务名称分开 - // 如果服务相同,但是创建套接字文件的用户不一样,greeter和lock不能删除对方的套接字文件,造成锁屏无法监听服务。 - QString serverName = QString("GrabKeyboard_") + (m_model->appType() == Login ? "greeter" : ("lock_" + m_model->currentUser()->name())); - // 将之前的server删除,如果是旧文件,即使监听成功,客户端也无法连接。 - QLocalServer::removeServer(serverName); - if (!m_localServer->listen(serverName)) { // 监听特定的连接 - qWarning() << "listen failed!" << m_localServer->errorString(); - } else { - qDebug() << "listen success!"; - } + // 将greeter和lock的服务名称分开 + // 如果服务相同,但是创建套接字文件的用户不一样,greeter和lock不能删除对方的套接字文件,造成锁屏无法监听服务。 + QString serverName = QString("GrabKeyboard_") + (m_model->appType() == AuthCommon::Login ? "greeter" : ("lock_" + m_model->currentUser()->name())); + // 将之前的server删除,如果是旧文件,即使监听成功,客户端也无法连接。 + QLocalServer::removeServer(serverName); + if (!m_localServer->listen(serverName)) { // 监听特定的连接 + qCWarning(DDE_SHELL) << "Listen local server failed!" << m_localServer->errorString(); } - once = true; + + DConfigHelper::instance()->bind(this, SHOW_MEDIA_WIDGET, &LockContent::OnDConfigPropertyChanged); } void LockContent::initUI() { - m_timeWidget = new TimeWidget(); - m_timeWidget->setAccessibleName("TimeWidget"); - setCenterTopWidget(m_timeWidget); - // 处理时间制跳转策略,获取到时间制再显示时间窗口 - m_timeWidget->setVisible(false); + m_centerTopWidget = new CenterTopWidget(this); + setCenterTopWidget(m_centerTopWidget); m_shutdownFrame = new ShutdownWidget; m_shutdownFrame->setAccessibleName("ShutdownFrame"); @@ -79,7 +128,7 @@ void LockContent::initUI() m_logoWidget->setAccessibleName("LogoWidget"); setLeftBottomWidget(m_logoWidget); - m_controlWidget = new ControlWidget(m_model); + m_controlWidget = new ControlWidget(m_model, this); m_controlWidget->setAccessibleName("ControlWidget"); setRightBottomWidget(m_controlWidget); @@ -91,31 +140,42 @@ void LockContent::initUI() m_authWidget->hide(); initUserListWidget(); + + if (PluginManager::instance()->getFullManagedLoginPlugin() != nullptr) { + initFMAWidget(); + } } void LockContent::initConnections() { connect(m_model, &SessionBaseModel::currentUserChanged, this, &LockContent::onCurrentUserChanged); - connect(m_controlWidget, &ControlWidget::requestSwitchUser, this, [ = ] { - m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); - emit requestEndAuthentication(m_model->currentUser()->name(), AT_All); + connect(m_controlWidget, &ControlWidget::requestSwitchUser, this, [this] { + if (!m_model->userlistVisible() && m_model->currentUser()->name() == "...") { + emit requestSwitchToUser(m_model->currentUser()); + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + } else { + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); + emit requestEndAuthentication(m_model->currentUser()->name(), AuthCommon::AT_All); + } }); - connect(m_controlWidget, &ControlWidget::requestShutdown, this, [ = ] { + connect(m_controlWidget, &ControlWidget::requestShutdown, this, [this] { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PowerMode); }); connect(m_controlWidget, &ControlWidget::requestSwitchVirtualKB, this, &LockContent::toggleVirtualKB); connect(m_controlWidget, &ControlWidget::requestShowModule, this, &LockContent::showModule); + connect(m_controlWidget, &ControlWidget::requestShowTrayModule, this, &LockContent::showTrayPopup); - //刷新背景单独与onStatusChanged信号连接,避免在showEvent事件时调用onStatusChanged而重复刷新背景,减少刷新次数 + // 刷新背景单独与onStatusChanged信号连接,避免在showEvent事件时调用onStatusChanged而重复刷新背景,减少刷新次数 connect(m_model, &SessionBaseModel::onStatusChanged, this, &LockContent::onStatusChanged); - //在锁屏显示时,启动onborad进程,锁屏结束时结束onboard进程 - auto initVirtualKB = [&](bool hasvirtualkb) { - if (hasvirtualkb && !m_virtualKB) { + //在锁屏显示时,启动onboard进程,锁屏结束时结束onboard进程 + auto initVirtualKB = [&](bool hasVirtualKB) { + if (hasVirtualKB && !m_virtualKB) { connect(&VirtualKBInstance::Instance(), &VirtualKBInstance::initFinished, this, [&] { m_virtualKB = VirtualKBInstance::Instance().virtualKBWidget(); m_controlWidget->setVirtualKBVisible(true); - }, Qt::QueuedConnection); + }, + Qt::QueuedConnection); VirtualKBInstance::Instance().init(); } else { VirtualKBInstance::Instance().stopVirtualKBProcess(); @@ -127,16 +187,35 @@ void LockContent::initConnections() connect(m_model, &SessionBaseModel::hasVirtualKBChanged, this, initVirtualKB, Qt::QueuedConnection); connect(m_model, &SessionBaseModel::userListChanged, this, &LockContent::onUserListChanged); connect(m_model, &SessionBaseModel::userListLoginedChanged, this, &LockContent::onUserListChanged); - connect(m_model, &SessionBaseModel::authFinished, this, &LockContent::restoreMode); + connect(m_model, &SessionBaseModel::authFinished, this, [this](bool successful) { + if (successful) + setVisible(false); + restoreMode(); + }); connect(m_model, &SessionBaseModel::MFAFlagChanged, this, [this](const bool isMFA) { isMFA ? initMFAWidget() : initSFAWidget(); // 当前中间窗口为空或者中间窗口就是验证窗口的时候显示验证窗口 if (!m_centerWidget || m_centerWidget == m_authWidget) - setCenterContent(m_authWidget, Qt::AlignTop, m_authWidget->getTopSpacing()); + setCenterContent(m_authWidget->getAuthWidget(), 0, Qt::AlignTop, calcTopSpacing(m_authWidget->getTopSpacing())); }); - connect(m_wmInter, &__wm::WorkspaceSwitched, this, &LockContent::currentWorkspaceChanged); + connect(m_wmInter, &com::deepin::wm::WorkspaceSwitched, this, &LockContent::currentWorkspaceChanged); connect(m_localServer, &QLocalServer::newConnection, this, &LockContent::onNewConnection); + connect(m_controlWidget, &ControlWidget::notifyKeyboardLayoutHidden, this, [this] { + if (!m_model->isUseWayland() && isVisible() && window()->windowHandle()) { + qCDebug(DDE_SHELL) << "Grab keyboard after keyboard layout hidden"; + window()->windowHandle()->setKeyboardGrabEnabled(true); + } + }); + + connect(m_model, &SessionBaseModel::showUserList, this, &LockContent::showUserList); + connect(m_model, &SessionBaseModel::showLockScreen, this, &LockContent::showLockScreen); + connect(m_model, &SessionBaseModel::showShutdown, this, &LockContent::showShutdown); + + // 连续按两次电源键导致锁屏界面失焦,无法接收到event,需重新抓取焦点 + connect(m_model, &SessionBaseModel::onPowerActionChanged, this, [this] { + tryGrabKeyboard(); + }); } /** @@ -144,7 +223,7 @@ void LockContent::initConnections() */ void LockContent::initMFAWidget() { - qDebug() << "LockContent::initMFAWidget:" << m_sfaWidget << m_mfaWidget; + qCDebug(DDE_SHELL) << "Init MFA widget, sfa widget: " << m_sfaWidget << ", mfa widget: " << m_mfaWidget; if (m_sfaWidget) { m_sfaWidget->hide(); delete m_sfaWidget; @@ -162,6 +241,17 @@ void LockContent::initMFAWidget() connect(m_mfaWidget, &MFAWidget::sendTokenToAuth, this, &LockContent::sendTokenToAuth); connect(m_mfaWidget, &MFAWidget::requestEndAuthentication, this, &LockContent::requestEndAuthentication); connect(m_mfaWidget, &MFAWidget::requestCheckAccount, this, &LockContent::requestCheckAccount); + connect(m_mfaWidget, &MFAWidget::requestCheckSameNameAccount, this, &LockContent::requestCheckSameNameAccount); + + connect(&MFASequenceControl::instance(), &MFASequenceControl::currentUIAuthTypeChanged, this, [&](int authType) { + Q_UNUSED(authType) + // 仅在当前处于认证界面上刷新 + auto isMFA = m_model->getAuthProperty().MFAFlag; + qCInfo(DDE_SHELL) << "model mfa flag" << isMFA; + if (m_model->currentModeState() == SessionBaseModel::ModeStatus::PasswordMode && isMFA) { + pushPasswordFrame(); + } + }); } /** @@ -169,7 +259,6 @@ void LockContent::initMFAWidget() */ void LockContent::initSFAWidget() { - qDebug() << "LockContent::initSFAWidget:" << m_sfaWidget << m_mfaWidget; if (m_mfaWidget) { m_mfaWidget->hide(); delete m_mfaWidget; @@ -187,10 +276,37 @@ void LockContent::initSFAWidget() connect(m_sfaWidget, &SFAWidget::sendTokenToAuth, this, &LockContent::sendTokenToAuth); connect(m_sfaWidget, &SFAWidget::requestEndAuthentication, this, &LockContent::requestEndAuthentication); connect(m_sfaWidget, &SFAWidget::requestCheckAccount, this, &LockContent::requestCheckAccount); + connect(m_sfaWidget, &SFAWidget::requestCheckSameNameAccount, this, &LockContent::requestCheckSameNameAccount); connect(m_sfaWidget, &SFAWidget::authFinished, this, &LockContent::authFinished); connect(m_sfaWidget, &SFAWidget::updateParentLayout, this, [this] { - m_centerSpacerItem->changeSize(0, m_sfaWidget->getTopSpacing()); + if (!m_sfaWidget->isVisible()) + return; + m_centerSpacerItem->changeSize(0, calcTopSpacing(m_sfaWidget->getTopSpacing())); + m_centerVLayout->invalidate(); }); + connect(m_sfaWidget, &AuthWidget::noPasswordLoginChanged, this, &LockContent::noPasswordLoginChanged); +} + +// init full managed plugin widget +void LockContent::initFMAWidget() +{ + if (m_fmaWidget) { + m_fmaWidget->hide(); + delete m_fmaWidget; + m_fmaWidget = nullptr; + } + + m_fmaWidget = new FullManagedAuthWidget(); + m_fmaWidget->setModel(m_model); + if (m_fmaWidget->isPluginLoaded()) { + setFullManagedLoginWidget(m_fmaWidget); + } + connect(m_fmaWidget, &FullManagedAuthWidget::requestStartAuthentication, this, &LockContent::requestStartAuthentication); + connect(m_fmaWidget, &FullManagedAuthWidget::sendTokenToAuth, this, &LockContent::sendTokenToAuth); + connect(m_fmaWidget, &FullManagedAuthWidget::requestEndAuthentication, this, &LockContent::requestEndAuthentication); + connect(m_fmaWidget, &FullManagedAuthWidget::requestCheckAccount, this, &LockContent::requestCheckAccount); + connect(m_fmaWidget, &FullManagedAuthWidget::requestCheckSameNameAccount, this, &LockContent::requestCheckSameNameAccount); + connect(m_fmaWidget, &FullManagedAuthWidget::authFinished, this, &LockContent::authFinished); } /** @@ -211,12 +327,12 @@ void LockContent::initUserListWidget() void LockContent::onCurrentUserChanged(std::shared_ptr user) { - if (user.get() == nullptr) return; // if dbus is async + if (user.get() == nullptr) + return; // if dbus is async //如果是锁屏就用系统语言,如果是登陆界面就用用户语言 auto locale = qApp->applicationName() == "dde-lock" ? QLocale::system().name() : user->locale(); m_logoWidget->updateLocale(locale); - m_timeWidget->updateLocale(locale); for (auto connect : m_currentUserConnects) { m_user.get()->disconnect(connect); @@ -226,59 +342,110 @@ void LockContent::onCurrentUserChanged(std::shared_ptr user) m_user = user; - m_timeWidget->set24HourFormat(user->isUse24HourFormat()); - m_timeWidget->setWeekdayFormatType(user->weekdayFormat()); - m_timeWidget->setShortDateFormat(user->shortDateFormat()); - m_timeWidget->setShortTimeFormat(user->shortTimeFormat()); - m_currentUserConnects << connect(user.get(), &User::greeterBackgroundChanged, this, &LockContent::updateGreeterBackgroundPath, Qt::UniqueConnection) - << connect(user.get(), &User::desktopBackgroundChanged, this, &LockContent::updateDesktopBackgroundPath, Qt::UniqueConnection) - << connect(user.get(), &User::use24HourFormatChanged, this, &LockContent::updateTimeFormat, Qt::UniqueConnection) - << connect(user.get(), &User::weekdayFormatChanged, m_timeWidget, &TimeWidget::setWeekdayFormatType) - << connect(user.get(), &User::shortDateFormatChanged, m_timeWidget, &TimeWidget::setShortDateFormat) - << connect(user.get(), &User::shortTimeFormatChanged, m_timeWidget, &TimeWidget::setShortTimeFormat); - - //TODO: refresh blur image - QTimer::singleShot(0, this, [ = ] { - updateTimeFormat(user->isUse24HourFormat()); - }); + << connect(user.get(), &User::desktopBackgroundChanged, this, &LockContent::updateDesktopBackgroundPath, Qt::UniqueConnection); + m_centerTopWidget->setCurrentUser(user.get()); m_logoWidget->updateLocale(locale); + + onUserListChanged(m_model->isServerModel() ? m_model->loginedUserList() : m_model->userList()); } void LockContent::pushPasswordFrame() { - setCenterContent(m_authWidget, Qt::AlignTop, m_authWidget->getTopSpacing()); + if (!m_model->userlistVisible()) { + if (m_model->currentUser()->name() == "...") { + m_controlWidget->setUserSwitchEnable(false); + } else { + m_controlWidget->setUserSwitchEnable(m_isUserSwitchVisible); + } + } + + setCenterContent(m_authWidget->getAuthWidget(), 0, Qt::AlignTop, calcTopSpacing(m_authWidget->getTopSpacing())); m_authWidget->syncResetPasswordUI(); + + if (m_fmaWidget && !m_fmaWidget->isPluginLoaded()) { + showDefaultFrame(); + return; + } + + showPasswdFrame(); } void LockContent::pushUserFrame() { - if(m_model->isServerModel()) + qCInfo(DDE_SHELL) << "Push user frame"; + + if (!m_model->userlistVisible()) { + std::shared_ptr user_ptr = m_model->findUserByName("..."); + if (user_ptr) { + m_controlWidget->setUserSwitchEnable(false); + emit requestSwitchToUser(user_ptr); + return; + } + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + return; + } + + if (m_model->isServerModel()) m_controlWidget->setUserSwitchEnable(false); - m_userListWidget->updateLayout(); + m_userListWidget->updateLayout(width()); setCenterContent(m_userListWidget); + + auto config = PluginConfigMap::instance().getConfig(); + if (config) { + m_controlWidget->setUserSwitchEnable(config->isUserSwitchButtonVisiable()); + } else { + m_controlWidget->setUserSwitchEnable(m_isUserSwitchVisible); + } + + showDefaultFrame(); + + // fix: 解决用户界面多账户区域无焦点问题 + // showDefaultFrame() -> hideStackedWidgets() -> 会将焦点置为空 + // 导致默认用户无选中状态,多账户区域无键盘事件 + setFocus(); + + // 用户列表界面显示时,设置锁屏状态为锁定 + // 主要是为了处理需求:切换用户界面属于进入锁屏,待机唤醒时仍进入锁屏界面,需输入密码进入系统。 + Q_EMIT requestLockStateChange(true); } void LockContent::pushConfirmFrame() { - setCenterContent(m_authWidget, Qt::AlignTop, m_authWidget->getTopSpacing()); + setCenterContent(m_authWidget->getAuthWidget(), 0, Qt::AlignTop, calcTopSpacing(m_authWidget->getTopSpacing())); + showDefaultFrame(); } void LockContent::pushShutdownFrame() { + qCInfo(DDE_SHELL) << "Push shutdown frame"; + // 设置关机选项界面大小为中间区域的大小,并移动到左上角,避免显示后出现移动现象 + auto config = PluginConfigMap::instance().getConfig(); + if (config) { + m_shutdownFrame->setUserSwitchEnable(config->isUserSwitchButtonVisiable()); + m_controlWidget->setUserSwitchEnable(config->isUserSwitchButtonVisiable()); + } else { + m_shutdownFrame->setUserSwitchEnable(m_isUserSwitchVisible); + m_controlWidget->setUserSwitchEnable(m_isUserSwitchVisible); + } + //设置关机选项界面大小为中间区域的大小,并移动到左上角,避免显示后出现移动现象 - QSize size = getCenterContentSize(); - m_shutdownFrame->setFixedSize(size); - m_shutdownFrame->move(0, 0); m_shutdownFrame->onStatusChanged(m_model->currentModeState()); setCenterContent(m_shutdownFrame); + showDefaultFrame(); } void LockContent::setMPRISEnable(const bool state) { + m_MPRISEnable = state; + + if (!m_showMediaWidget) { + return; + } + if (!m_mediaWidget) { m_mediaWidget = new MediaWidget; m_mediaWidget->setAccessibleName("MediaWidget"); @@ -289,32 +456,78 @@ void LockContent::setMPRISEnable(const bool state) setCenterBottomWidget(m_mediaWidget); } +void LockContent::enableSystemShortcut(const QStringList &shortcuts, bool enabled, bool isPersistent) +{ + QDBusInterface inter(DSS_DBUS::keybindingService, DSS_DBUS::keybindingPath, DSS_DBUS::keybindingService, QDBusConnection::sessionBus()); + QList argumentList; + argumentList << QVariant::fromValue(shortcuts) << QVariant::fromValue(enabled) << QVariant::fromValue(isPersistent); + inter.asyncCallWithArgumentList(QStringLiteral("EnableSystemShortcut"), argumentList); +} + void LockContent::onNewConnection() { + // 重置密码界面显示前需要隐藏插件右键菜单,避免抢占键盘 + Q_EMIT m_model->hidePluginMenu(); + + // 重置密码程序启动连接成功锁屏界面才释放键盘,避免点击重置密码过程中使用快捷键切走锁屏 + if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(false)) { + qCDebug(DDE_SHELL) << "Set keyboard grab enabled to false success!"; + } + if (m_localServer->hasPendingConnections()) { QLocalSocket *socket = m_localServer->nextPendingConnection(); connect(socket, &QLocalSocket::disconnected, this, &LockContent::onDisConnect); - connect(socket, &QLocalSocket::readyRead, this, [socket, this] { - auto content = socket->readAll(); - if (content == "close") { - m_sfaWidget->syncPasswordResetPasswordVisibleChanged(QVariant::fromValue(true)); - m_sfaWidget->syncResetPasswordUI(); - } - }); } + + // 仅在锁屏界面使用 + if (m_model->appType() == AuthCommon::Lock) { + enableSystemShortcut(QStringList() << "screenshot" + << "screenshot-window" + << "screenshot-delayed" + << "screenshot-ocr" + << "screenshot-scroll" + << "deepin-screen-recorder", + false, false); + } + m_hasResetPasswordDialog = true; } void LockContent::onDisConnect() { - tryGrabKeyboard(); + if (m_authWidget) { + m_authWidget->syncPasswordResetPasswordVisibleChanged(QVariant::fromValue(true)); + m_authWidget->syncResetPasswordUI(); + } + // 这种情况下不必强制要求可以抓取到键盘,因为可能是网络弹窗抓取了键盘 + tryGrabKeyboard(false); + enableSystemShortcut(QStringList() << "screenshot" + << "screenshot-window" + << "screenshot-delayed" + << "screenshot-ocr" + << "screenshot-scroll" + << "deepin-screen-recorder", + true, false); } void LockContent::onStatusChanged(SessionBaseModel::ModeStatus status) { + qCInfo(DDE_SHELL) << "Incoming status:" << status << ", current status:" << m_currentModeStatus; refreshLayout(status); - if(m_model->isServerModel()) + // select plugin config + if (m_fmaWidget && m_fmaWidget->isPluginLoaded()) { + PluginConfigMap::instance().requestAddConfig(PluginConfigMap::ConfigIndex::FullManagePlugin, m_fmaWidget); + } else { + PluginConfigMap::instance().requestRemoveConfig(PluginConfigMap::ConfigIndex::FullManagePlugin); + } + + if (m_model->isServerModel()) onUserListChanged(m_model->loginedUserList()); + + if (!m_isPANGUCpu && m_currentModeStatus == status) + return; + m_currentModeStatus = status; + switch (status) { case SessionBaseModel::ModeStatus::PasswordMode: pushPasswordFrame(); @@ -346,14 +559,18 @@ void LockContent::mouseReleaseEvent(QMouseEvent *event) //在关机界面没有点击按钮直接点击界面时,直接隐藏关机界面 if (m_model->currentModeState() == SessionBaseModel::ShutDownMode) { - hideToplevelWindow(); + m_model->setVisible(false); } if (m_model->currentModeState() == SessionBaseModel::UserMode || m_model->currentModeState() == SessionBaseModel::PowerMode) { - // 触屏点击空白处不退出用户列表界面 - if (event->source() == Qt::MouseEventSynthesizedByQt) + + // 在用户列表界面,用户达到一定数量需要支持滚动,触屏滚动容易触发回到当前用户界面 + // ,所以这个界面触屏点击空白处不退出用户列表界面 + if (event->source() == Qt::MouseEventSynthesizedByQt + && m_model->currentModeState() == SessionBaseModel::UserMode) { return SessionBaseWindow::mouseReleaseEvent(event); + } // 点击空白处的时候切换到当前用户,以开启验证。 emit requestSwitchToUser(m_model->currentUser()); @@ -367,6 +584,10 @@ void LockContent::mouseReleaseEvent(QMouseEvent *event) void LockContent::showEvent(QShowEvent *event) { onStatusChanged(m_model->currentModeState()); + // 重新设置一下焦点,否则用户列表界面切换屏幕的时候焦点异常 + if (m_centerWidget) + m_centerWidget->setFocus(); + tryGrabKeyboard(); QFrame::showEvent(event); } @@ -379,18 +600,21 @@ void LockContent::hideEvent(QHideEvent *event) void LockContent::resizeEvent(QResizeEvent *event) { - QTimer::singleShot(0, this, [ = ] { + QTimer::singleShot(0, this, [this] { if (m_virtualKB && m_virtualKB->isVisible()) { updateVirtualKBPosition(); } }); if (SessionBaseModel::PasswordMode == m_model->currentModeState() || (SessionBaseModel::ConfirmPasswordMode == m_model->currentModeState())) { - m_centerSpacerItem->changeSize(0, m_authWidget->getTopSpacing()); - m_centerVLayout->update(); + m_centerSpacerItem->changeSize(0, calcTopSpacing(m_authWidget->getTopSpacing())); + m_centerVLayout->invalidate(); + QTimer::singleShot(0, this, [ = ] { + m_authWidget->updatePasswordErrortipUi(); + }); } - return SessionBaseWindow::resizeEvent(event); + SessionBaseWindow::resizeEvent(event); } void LockContent::restoreMode() @@ -404,9 +628,7 @@ void LockContent::updateGreeterBackgroundPath(const QString &path) return; } - if (m_model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode) { - emit requestBackground(path); - } + emit requestBackground(path); } void LockContent::updateDesktopBackgroundPath(const QString &path) @@ -415,18 +637,32 @@ void LockContent::updateDesktopBackgroundPath(const QString &path) return; } - if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { - emit requestBackground(path); - } + emit requestBackground(path); } -void LockContent::updateTimeFormat(bool use24) +void LockContent::OnDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) { - if (m_user != nullptr) { - auto locale = qApp->applicationName() == "dde-lock" ? QLocale::system().name() : m_user->locale(); - m_timeWidget->updateLocale(locale); - m_timeWidget->set24HourFormat(use24); - m_timeWidget->setVisible(true); + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == SHOW_MEDIA_WIDGET) { + if (value.toBool()) { + if (!obj->m_mediaWidget) { + obj->m_mediaWidget = new MediaWidget; + obj->m_mediaWidget->setAccessibleName("MediaWidget"); + obj->m_mediaWidget->initMediaPlayer(); + } + + obj->m_mediaWidget->setVisible(obj->m_MPRISEnable); + obj->setCenterBottomWidget(obj->m_mediaWidget); + } else { + if (obj->m_mediaWidget) { + obj->m_mediaWidget->setVisible(false); + obj->m_mediaWidget->deleteLater(); + obj->m_mediaWidget = nullptr; + } + } } } @@ -434,9 +670,9 @@ void LockContent::toggleVirtualKB() { if (!m_virtualKB) { VirtualKBInstance::Instance(); - QTimer::singleShot(500, this, [ = ] { + QTimer::singleShot(500, this, [this] { m_virtualKB = VirtualKBInstance::Instance().virtualKBWidget(); - qDebug() << "init virtualKB over." << m_virtualKB; + qCDebug(DDE_SHELL) << "Init virtual keyboard over: " << m_virtualKB; toggleVirtualKB(); }); return; @@ -450,78 +686,165 @@ void LockContent::toggleVirtualKB() m_virtualKB->setVisible(!m_virtualKB->isVisible()); } -void LockContent::showModule(const QString &name) +void LockContent::showModule(const QString &name, const bool callShowForce) { - BaseModuleInterface *module = ModulesLoader::instance().findModuleByName(name); - if (!module) { + PluginBase *plugin = PluginManager::instance()->findPlugin(name); + if (!plugin) { return; } - switch (module->type()) { - case BaseModuleInterface::LoginType: - m_loginWidget = module->content(); + switch (plugin->type()) { + case PluginBase::ModuleType::LoginType: + m_loginWidget = plugin->content(); setCenterContent(m_loginWidget); m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); break; - case BaseModuleInterface::TrayType: - m_loginWidget = module->content(); - setCenterContent(m_loginWidget); + case PluginBase::ModuleType::TrayType: { + m_currentTray = m_controlWidget->getTray(name); + if (!m_currentTray || !plugin->content()) { + qCWarning(DDE_SHELL) << "TrayButton or plugin`s content is null"; + return; + } + showTrayPopup(m_currentTray, plugin->content(), callShowForce); + break; + } + default: + // 扩展插件类型 FullManagedLoginType,不在此处处理 break; } } +bool LockContent::eventFilter(QObject *watched, QEvent *e) +{ + // 点击插件弹窗以外区域,隐藏插件弹窗 + if (m_popWin && m_currentTray && m_popWin->isVisible()) { + QWidget *w = qobject_cast(watched); + if (!w) + return false; + const bool isChild = m_currentTray->findChildren().contains(w); + if ((watched == m_currentTray || isChild) && e->type() == QEvent::Enter) { + Q_EMIT qobject_cast(m_currentTray)->requestHideTips(); + } else if (watched != m_currentTray && !isChild && e->type() == QEvent::MouseButtonRelease) { + if (!m_popWin->geometry().contains(this->mapFromGlobal(QCursor::pos()))) { + m_popWin->hide(); + } + } + } + + return false; +} + +bool LockContent::event(QEvent *event) +{ + if (event->type() == QEvent::WindowDeactivate) { + if (m_popWin && m_currentTray && m_popWin->isVisible()) { + m_popWin->activateWindow(); + } + } + return SessionBaseWindow::event(event); +} + void LockContent::updateVirtualKBPosition() { const QPoint point = mapToParent(QPoint((width() - m_virtualKB->width()) / 2, height() - m_virtualKB->height() - 50)); m_virtualKB->move(point); } -void LockContent::onUserListChanged(QList > list) +void LockContent::onUserListChanged(QList> list) { const bool allowShowUserSwitchButton = m_model->allowShowUserSwitchButton(); const bool alwaysShowUserSwitchButton = m_model->alwaysShowUserSwitchButton(); - bool haveLogindUser = true; + bool haveLoginedUser = true; + + if (m_model->isServerModel() && m_model->appType() == AuthCommon::Login) { + haveLoginedUser = !m_model->loginedUserList().isEmpty(); + } - if (m_model->isServerModel() && m_model->appType() == Login) { - haveLogindUser = !m_model->loginedUserList().isEmpty(); + int userList = list.size(); + if (!m_model->isServerModel() && !m_model->userlistVisible()) { + foreach (auto user, list) { + if (user->name() == "...") { + userList--; + } + } } - bool enable = (alwaysShowUserSwitchButton || - (allowShowUserSwitchButton && - (list.size() > (m_model->isServerModel() ? 0 : 1)))) && - haveLogindUser; + bool enable = (alwaysShowUserSwitchButton || (allowShowUserSwitchButton && (userList > (m_model->isServerModel() ? 0 : 1)))) && haveLoginedUser; - m_controlWidget->setUserSwitchEnable(enable); + bool controlEnable = enable && (m_model->userlistVisible() || m_model->currentUser()->name() != "..."); + m_controlWidget->setUserSwitchEnable(controlEnable); m_shutdownFrame->setUserSwitchEnable(enable); + + m_isUserSwitchVisible = enable; } -void LockContent::tryGrabKeyboard() +/** + * @brief 抓取键盘,失败后继续抓取,最多尝试15次. + * + * @param exitIfFailed true: 发送失败通知,并隐藏锁屏。 false:不做任何处理。 + */ +void LockContent::tryGrabKeyboard(bool exitIfFailed) { #ifndef QT_DEBUG - if (m_model->isUseWayland()) { + if (!isVisible()) { return; } - if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(true)) { - m_failures = 0; - return; + if (m_model->isUseWayland()) { + static QDBusInterface *kwinInter = new QDBusInterface("org.kde.KWin", "/KWin", "org.kde.KWin", QDBusConnection::sessionBus()); + if (!kwinInter || !kwinInter->isValid()) { + qCWarning(DDE_SHELL) << "Kwin interface is invalid"; + m_failures = 0; + return; + } + // wayland下判断是否有应用发起grab + QDBusReply reply = kwinInter->call("xwaylandGrabed"); + if (!reply.isValid() || !reply.value()) { + m_failures = 0; + return; + } + } else { + if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(true)) { + m_failures = 0; + return; + } + } + + if (m_failures > 5) { + qCWarning(DDE_SHELL) << "Trying ungrab keyboard in lock content"; + KeyboardMonitor::instance()->ungrabKeyboard(); } m_failures++; if (m_failures == 15) { - qWarning() << "Trying grabkeyboard has exceeded the upper limit. dde-lock will quit."; + qCWarning(DDE_SHELL) << "Trying to grab keyboard has exceeded the upper limit"; m_failures = 0; + if (!exitIfFailed) { + return; + } + + if (m_hasResetPasswordDialog) { + qCWarning(DDE_SHELL) << "There is a reset password dialog, can not grab keyboard"; + return; + } + DDBusSender() .service("org.freedesktop.Notifications") .path("/org/freedesktop/Notifications") .interface("org.freedesktop.Notifications") .method(QString("Notify")) +#ifndef ENABLE_DSS_SNIPE .arg(tr("Lock Screen")) .arg(static_cast(0)) .arg(QString("")) +#else + .arg(QString("dde-lock")) // appName + .arg(static_cast(0)) + .arg(QString("notification-lock-screen-failed")) +#endif .arg(QString("")) .arg(tr("Failed to lock screen")) .arg(QStringList()) @@ -529,39 +852,36 @@ void LockContent::tryGrabKeyboard() .arg(5000) .call(); + DDBusSender() + .service(DSS_DBUS::screenSaveService) + .path("/org/freedesktop/ScreenSaver") + .interface("org.freedesktop.ScreenSaver") + .method(QString("SimulateUserActivity")) + .call(); + + qCInfo(DDE_SHELL) << "Request hide lock frame"; emit requestLockFrameHide(); return; } - QTimer::singleShot(100, this, &LockContent::tryGrabKeyboard); + QTimer::singleShot(100, this, [this, exitIfFailed] { + tryGrabKeyboard(exitIfFailed); + }); #endif } -void LockContent::hideToplevelWindow() -{ - QWidgetList widgets = qApp->topLevelWidgets(); - for (QWidget *widget : widgets) { - if (widget->isVisible()) { - widget->hide(); - } - } -} - void LockContent::currentWorkspaceChanged() { QDBusPendingCall call = m_wmInter->GetCurrentWorkspaceBackgroundForMonitor(QGuiApplication::primaryScreen()->name()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, &QDBusPendingCallWatcher::finished, [ = ] { - if (!call.isError()) - { + connect(watcher, &QDBusPendingCallWatcher::finished, [=] { + if (!call.isError()) { QDBusReply reply = call.reply(); updateWallpaper(reply.value()); - } else - { - qWarning() << "get current workspace background error: " << call.error().message(); + } else { + qCWarning(DDE_SHELL) << "Get current workspace background error: " << call.error().message(); updateWallpaper("/usr/share/backgrounds/deepin/desktop.jpg"); } - watcher->deleteLater(); }); } @@ -594,6 +914,62 @@ void LockContent::refreshLayout(SessionBaseModel::ModeStatus status) setBottomFrameVisible(status != SessionBaseModel::ModeStatus::ShutDownMode); } +void LockContent::showTrayPopup(QWidget *trayWidget, QWidget *contentWidget, const bool callShowForce) +{ + if (!trayWidget || !contentWidget) { + return; + } + + if (!m_popWin) { + m_popWin = new PopupWindow(this); + connect(m_model, &SessionBaseModel::visibleChanged, this, [this] (const bool visible) { + if (!visible) { + m_popWin->hide(); + } + }); + connect(m_popWin, &PopupWindow::visibleChanged, this, [this] (bool visible) { + m_controlWidget->setCanShowMenu(!visible); + // BUG-134087, tray popup窗口隐藏后,锁屏界面需要重新抓取键盘 + if (!visible && !m_model->isUseWayland() && isVisible() && window()->windowHandle()) { + qCDebug(DDE_SHELL) << "Grab keyboard after keyboard layout hidden"; + window()->windowHandle()->setKeyboardGrabEnabled(true); + } + }); + + connect(this, &LockContent::parentChanged, this, [this] { + if (m_popWin && m_popWin->isVisible()) { + const QPoint &point = mapFromGlobal(m_currentTray->mapToGlobal(QPoint(m_currentTray->size().width() / 2, 0))); + m_popWin->show(point); + } + }); + + // for BUG-256133 + connect(m_model, &SessionBaseModel::onStatusChanged, this, [this] (SessionBaseModel::ModeStatus status) { + if (status != SessionBaseModel::ModeStatus::PasswordMode) { + m_popWin->hide(); + } + }); + } + + m_currentTray = trayWidget; + + // 隐藏后需要removeEventFilter,后期优化 + for (auto child : this->findChildren()) { + child->removeEventFilter(this); + child->installEventFilter(this); + } + + if (!m_popWin->getContent() || m_popWin->getContent() != contentWidget) + m_popWin->setContent(contentWidget); + + const QPoint point = mapFromGlobal(m_currentTray->mapToGlobal(QPoint(m_currentTray->size().width() / 2, 0))); + // 插件图标不显示,窗口不显示 + if (m_currentTray->isVisible()) { + m_popWin->move(point.x(), point.y()); + callShowForce ? m_popWin->show(point) : m_popWin->toggle(point); + } +} + void LockContent::keyPressEvent(QKeyEvent *event) { switch (event->key()) { @@ -607,12 +983,40 @@ void LockContent::keyPressEvent(QKeyEvent *event) if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ConfirmPasswordMode) { m_model->setAbortConfirm(false); m_model->setPowerAction(SessionBaseModel::PowerAction::None); + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } else if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { - hideToplevelWindow(); m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + m_model->setVisible(false); } else if (m_model->currentModeState() == SessionBaseModel::ModeStatus::PowerMode) { m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); } break; } } + +void LockContent::showUserList() +{ + if (m_model->userlistVisible()) { + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::UserMode); + QTimer::singleShot(10, this, [=] { + m_model->setVisible(true); + }); + } else { + std::shared_ptr user_ptr = m_model->findUserByName("..."); + if (user_ptr) { + emit requestSwitchToUser(user_ptr); + } + } +} + +void LockContent::showLockScreen() +{ + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::PasswordMode); + m_model->setVisible(true); +} + +void LockContent::showShutdown() +{ + m_model->setCurrentModeState(SessionBaseModel::ModeStatus::ShutDownMode); + m_model->setVisible(true); +} diff --git a/src/session-widgets/lockcontent.h b/src/session-widgets/lockcontent.h index 95f85b7f..5dadaf58 100644 --- a/src/session-widgets/lockcontent.h +++ b/src/session-widgets/lockcontent.h @@ -1,55 +1,67 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef LOCKCONTENT_H #define LOCKCONTENT_H -#include -#include - -#include - #include "mediawidget.h" #include "sessionbasemodel.h" #include "sessionbasewindow.h" -#include "systemmonitor.h" +#include "centertopwidget.h" +#include "popupwindow.h" +#include +#include + +#include +#ifndef ENABLE_DSS_SNIPE #include +#else +#include "wminterface.h" +#endif class AuthWidget; class MFAWidget; class SFAWidget; class UserFrameList; class ControlWidget; -class UserInputWidget; class User; class ShutdownWidget; class LogoWidget; -class TimeWidget; +class FullManagedAuthWidget; class LockContent : public SessionBaseWindow { Q_OBJECT public: - explicit LockContent(SessionBaseModel *const model, QWidget *parent = nullptr); - + explicit LockContent(QWidget *parent = nullptr); + static LockContent *instance(); + void init(SessionBaseModel *model); virtual void onCurrentUserChanged(std::shared_ptr user); virtual void onStatusChanged(SessionBaseModel::ModeStatus status); virtual void restoreMode(); void updateGreeterBackgroundPath(const QString &path); void updateDesktopBackgroundPath(const QString &path); + void hideEvent(QHideEvent *event) override; + static void OnDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); signals: void requestBackground(const QString &path); void requestSwitchToUser(std::shared_ptr user); void requestSetLayout(std::shared_ptr user, const QString &value); void unlockActionFinish(); - - void requestStartAuthentication(const QString &account, const int authType); - void sendTokenToAuth(const QString &account, const int authType, const QString &token); - void requestEndAuthentication(const QString &account, const int authType); + void requestStartAuthentication(const QString &account, const AuthFlags authType); + void sendTokenToAuth(const QString &account, const AuthType authType, const QString &token); + void requestEndAuthentication(const QString &account, const AuthFlags authType); void authFinished(); - - void requestCheckAccount(const QString &account); + void requestCheckSameNameAccount(const QString &account, bool switchUser); + void requestCheckAccount(const QString &account, bool switchUser); void requestLockFrameHide(); + void parentChanged(); + void noPasswordLoginChanged(const QString &account, bool noPassword); + void requestLockStateChange(const bool locked); public slots: void pushPasswordFrame(); @@ -59,54 +71,69 @@ public slots: void setMPRISEnable(const bool state); void onNewConnection(); void onDisConnect(); + void showUserList(); + void showLockScreen(); + void showShutdown(); protected: void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; - void hideEvent(QHideEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *watched, QEvent *e) Q_DECL_OVERRIDE; + bool event(QEvent *event) Q_DECL_OVERRIDE; protected: - void updateTimeFormat(bool use24); void toggleVirtualKB(); - void showModule(const QString &name); + void showModule(const QString &name, const bool callShowForce); void updateVirtualKBPosition(); void onUserListChanged(QList> list); - void tryGrabKeyboard(); - void hideToplevelWindow(); + void tryGrabKeyboard(bool exitIfFalied = true); void currentWorkspaceChanged(); void updateWallpaper(const QString &path); void refreshBackground(SessionBaseModel::ModeStatus status); void refreshLayout(SessionBaseModel::ModeStatus status); + void showTrayPopup(QWidget *trayWidget, QWidget *contentWidget, const bool callShowForce); void initUI(); void initConnections(); void initMFAWidget(); void initSFAWidget(); + void initFMAWidget(); void initUserListWidget(); + void enableSystemShortcut(const QStringList &shortcuts, bool enabled, bool isPersistent); protected: - SessionBaseModel *m_model; - ControlWidget *m_controlWidget; - ShutdownWidget *m_shutdownFrame; - QWidget *m_virtualKB; + SessionBaseModel *m_model = nullptr; + ControlWidget *m_controlWidget = nullptr; + CenterTopWidget *m_centerTopWidget = nullptr; + ShutdownWidget *m_shutdownFrame = nullptr; + QPointer m_virtualKB = nullptr; std::shared_ptr m_user; QList m_currentUserConnects; - LogoWidget *m_logoWidget; - TimeWidget *m_timeWidget; + LogoWidget *m_logoWidget = nullptr; MediaWidget *m_mediaWidget = nullptr; - com::deepin::wm *m_wmInter; - QWidget *m_loginWidget; - QMap m_centeralWidgets; + com::deepin::wm *m_wmInter = nullptr; + QWidget *m_loginWidget = nullptr; - SFAWidget *m_sfaWidget; - MFAWidget *m_mfaWidget; - AuthWidget *m_authWidget; - UserFrameList *m_userListWidget; + SFAWidget *m_sfaWidget = nullptr; + MFAWidget *m_mfaWidget = nullptr; + AuthWidget *m_authWidget = nullptr; + FullManagedAuthWidget *m_fmaWidget = nullptr; + UserFrameList *m_userListWidget = nullptr; int m_failures = 0; - QLocalServer *m_localServer; + QLocalServer *m_localServer = nullptr; + SessionBaseModel::ModeStatus m_currentModeStatus; + bool m_initialized = false; + bool m_isUserSwitchVisible = false; + PopupWindow *m_popWin = nullptr; + QPointer m_currentTray = nullptr; + + bool m_isPANGUCpu = false; + bool m_MPRISEnable = false; + bool m_showMediaWidget = false; + bool m_hasResetPasswordDialog = false; }; #endif // LOCKCONTENT_H diff --git a/src/session-widgets/mfa_widget.cpp b/src/session-widgets/mfa_widget.cpp index c850e513..e99818d2 100644 --- a/src/session-widgets/mfa_widget.cpp +++ b/src/session-widgets/mfa_widget.cpp @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "mfa_widget.h" @@ -27,15 +10,19 @@ #include "auth_password.h" #include "auth_ukey.h" #include "dlineeditex.h" -#include "framedatabind.h" #include "keyboardmonitor.h" #include "sessionbasemodel.h" #include "useravatar.h" +#include "mfasequencecontrol.h" +#include "plugin_manager.h" +#include "auth_custom.h" +#include "signal_bridge.h" MFAWidget::MFAWidget(QWidget *parent) : AuthWidget(parent) , m_index(0) , m_mainLayout(new QVBoxLayout(this)) + , m_authLayout(new QVBoxLayout) { setObjectName(QStringLiteral("MFAWidget")); setAccessibleName(QStringLiteral("MFAWidget")); @@ -47,19 +34,22 @@ MFAWidget::MFAWidget(QWidget *parent) void MFAWidget::initUI() { AuthWidget::initUI(); - /* 用户名输入框 */ - std::function accountChanged = std::bind(&MFAWidget::syncAccount, this, std::placeholders::_1); - m_registerFunctions["MFAAccount"] = FrameDataBind::Instance()->registerFunction("MFAAccount", accountChanged); - FrameDataBind::Instance()->refreshData("MFAAccount"); - + m_authLayout->setSpacing(10); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_authLayout->setContentsMargins(0, 0, 0, 0); +#else + m_authLayout->setMargin(0); +#endif + + m_mainLayout->setSpacing(0); m_mainLayout->setContentsMargins(10, 0, 10, 0); - m_mainLayout->setSpacing(10); - m_mainLayout->addWidget(m_userAvatar); - m_mainLayout->addWidget(m_nameLabel, 0, Qt::AlignVCenter); - m_mainLayout->addWidget(m_accountEdit, 0, Qt::AlignVCenter); - m_mainLayout->addSpacing(10); + SpacerItemBinder::addWidget(m_userAvatar, m_mainLayout, Qt::AlignVCenter, 0); + SpacerItemBinder::addWidget(m_accountEdit, m_mainLayout, Qt::AlignVCenter, 24); + SpacerItemBinder::addWidget(m_userNameWidget, m_mainLayout, Qt::AlignVCenter, 24); + m_mainLayout->addLayout(m_authLayout); + m_mainLayout->addSpacing(20); m_mainLayout->addWidget(m_expiredStateLabel); - m_mainLayout->addItem(m_expiredSpacerItem); + m_mainLayout->addSpacing(10); m_mainLayout->addWidget(m_lockButton, 0, Qt::AlignCenter); } @@ -68,8 +58,9 @@ void MFAWidget::initConnections() AuthWidget::initConnections(); connect(m_model, &SessionBaseModel::authTypeChanged, this, &MFAWidget::setAuthType); connect(m_model, &SessionBaseModel::authStateChanged, this, &MFAWidget::setAuthState); - connect(m_accountEdit, &DLineEditEx::textChanged, this, [](const QString &value) { - FrameDataBind::Instance()->updateValue("MFAAccount", value); + // 关闭--已开启但无UI的认证(针对手势这种开启功能,但可能因配置错误、未安装插件,导致无法完成登录/解锁的场景) + connect(&MFASequenceControl::instance(), &MFASequenceControl::requestEndUnsupportedAuth, this, [&](int authType) { + Q_EMIT requestEndAuthentication(m_model->currentUser()->name(), AUTH_FLAGS_CAST(authType)); }); } @@ -84,10 +75,9 @@ void MFAWidget::setModel(const SessionBaseModel *model) setUser(model->currentUser()); } -void MFAWidget::setAuthType(const int type) +void MFAWidget::setAuthType(const AuthFlags type) { - qDebug() << "MFAWidget::setAuthType:" << type; - m_index = 2; + m_index = 0; /* 面容 */ if (type & AT_Face) { initFaceAuth(); @@ -128,21 +118,29 @@ void MFAWidget::setAuthType(const int type) m_passwordAuth->deleteLater(); m_passwordAuth = nullptr; } + /* 手势 */ + if (type & AT_Pattern) { + initGestureAuth(); + } else if (m_gestureAuth) { + m_gestureAuth->deleteLater(); + m_gestureAuth = nullptr; + } + /* 账户 */ if (type == AT_None) { if (m_model->currentUser()->isNoPasswordLogin()) { m_lockButton->setEnabled(true); m_accountEdit->hide(); - m_nameLabel->show(); + m_userNameWidget->show(); } else { m_accountEdit->clear(); m_accountEdit->show(); - m_nameLabel->hide(); + m_userNameWidget->hide(); } } else { const bool visible = m_model->isServerModel() && m_model->appType() == Login; m_accountEdit->setVisible(visible); - m_nameLabel->setVisible(!visible); + m_userNameWidget->setVisible(!visible); } updatePasswordExpiredState(); @@ -176,6 +174,8 @@ void MFAWidget::setAuthType(const int type) } } setFocus(); + + MFASequenceControl::instance().setAuthType(type); } /** @@ -184,43 +184,39 @@ void MFAWidget::setAuthType(const int type) * @param state 认证结果 * @param message 消息 */ -void MFAWidget::setAuthState(const int type, const int state, const QString &message) +void MFAWidget::setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) { - qDebug() << "MFAWidget::setAuthState:" << type << state << message; switch (type) { case AT_Password: if (m_passwordAuth) { m_passwordAuth->setAuthState(state, message); - FrameDataBind::Instance()->updateValue("MFPasswordAuthState", state); - FrameDataBind::Instance()->updateValue("MFPasswordAuthMsg", message); } break; case AT_Fingerprint: if (m_fingerprintAuth) { m_fingerprintAuth->setAuthState(state, message); - FrameDataBind::Instance()->updateValue("MFFingerprintAuthState", state); - FrameDataBind::Instance()->updateValue("MFFingerprintAuthMsg", message); } break; case AT_Ukey: if (m_ukeyAuth) { m_ukeyAuth->setAuthState(state, message); - FrameDataBind::Instance()->updateValue("MFUKeyAuthState", state); - FrameDataBind::Instance()->updateValue("MFUKeyAuthMsg", message); } break; case AT_Face: if (m_faceAuth) { m_faceAuth->setAuthState(state, message); - FrameDataBind::Instance()->updateValue("MFFaceAuthState", state); - FrameDataBind::Instance()->updateValue("MFFaceAuthMsg", message); } break; case AT_Iris: if (m_irisAuth) { m_irisAuth->setAuthState(state, message); - FrameDataBind::Instance()->updateValue("MFIrisAuthState", state); - FrameDataBind::Instance()->updateValue("MFIrisAuthMsg", message); + } + break; + case AT_Pattern: + if (m_gestureAuth) { + m_gestureAuth->setAuthState(state, message); + // 插件需要认证结果 + m_gestureAuth->notifyAuthState(type, state); } break; case AT_All: @@ -229,6 +225,8 @@ void MFAWidget::setAuthState(const int type, const int state, const QString &mes default: break; } + + MFASequenceControl::instance().onAuthStatusChanged(type, state, message); } void MFAWidget::autoUnlock() @@ -245,14 +243,17 @@ void MFAWidget::initPasswdAuth() { if (m_passwordAuth) { m_passwordAuth->reset(); - m_mainLayout->insertWidget(m_index, m_passwordAuth); + m_authLayout->insertWidget(m_index, m_passwordAuth); return; } m_passwordAuth = new AuthPassword(this); m_passwordAuth->setCurrentUid(m_model->currentUser()->uid()); - m_passwordAuth->setCapsLockVisible(m_capslockMonitor->isCapslockOn()); + m_passwordAuth->setCapsLockVisible(KeyboardMonitor::instance()->isCapsLockOn()); m_passwordAuth->setPasswordHint(m_user->passwordHint()); - m_mainLayout->insertWidget(m_index, m_passwordAuth); + m_passwordAuth->setAuthStatueVisible(true); + m_passwordAuth->setPasswordLineEditEnabled(m_model->currentUser()->allowToChangePassword() || m_model->appType() != Login); + + m_authLayout->insertWidget(m_index, m_passwordAuth); connect(m_passwordAuth, &AuthPassword::activeAuth, this, [this] { emit requestStartAuthentication(m_model->currentUser()->name(), AT_Password); @@ -262,32 +263,23 @@ void MFAWidget::initPasswdAuth() if (text.isEmpty()) { return; } + if (m_passwordAuth->assistLoginWidget()) { + if (m_user) { + Q_EMIT SignalBridge::ref().requestSendExtraInfo(m_user->name(), AT_Password, m_passwordAuth->assistLoginWidget()->extraInfo()); + } else { + qCWarning(DDE_SHELL) << "Current user is null, can not send extra info"; + } + } m_passwordAuth->setAuthStateStyle(LOGIN_SPINNER); m_passwordAuth->setAnimationState(true); m_passwordAuth->setLineEditEnabled(false); emit sendTokenToAuth(m_model->currentUser()->name(), AT_Password, text); }); - connect(m_passwordAuth, &AuthPassword::authFinished, this, [this](const int value) { + connect(m_passwordAuth, &AuthPassword::authFinished, this, [this](const AuthState value) { checkAuthResult(AT_Password, value); }); connect(m_lockButton, &QPushButton::clicked, m_passwordAuth, &AuthPassword::requestAuthenticate); - connect(m_capslockMonitor, &KeyboardMonitor::capslockStatusChanged, m_passwordAuth, &AuthPassword::setCapsLockVisible); - - /* 输入框数据同步 */ - std::function passwordChanged = std::bind(&MFAWidget::syncPassword, this, std::placeholders::_1); - m_registerFunctions["MFPasswordAuth"] = FrameDataBind::Instance()->registerFunction("MFPasswordAuth", passwordChanged); - connect(m_passwordAuth, &AuthPassword::lineEditTextChanged, this, [](const QString &value) { - FrameDataBind::Instance()->updateValue("MFPasswordAuth", value); - }); - FrameDataBind::Instance()->refreshData("MFPasswordAuth"); - /* 重置密码可见性数据同步 */ - std::function resetPasswordVisibleChanged = std::bind(&AuthWidget::syncPasswordResetPasswordVisibleChanged, this, std::placeholders::_1); - m_registerFunctions["MFResetPasswordVisible"] = FrameDataBind::Instance()->registerFunction("MFResetPasswordVisible", resetPasswordVisibleChanged); - connect(m_passwordAuth, &AuthPassword::resetPasswordMessageVisibleChanged, this, [ = ](const bool value) { - FrameDataBind::Instance()->updateValue("MFResetPasswordVisible", value); - }); - FrameDataBind::Instance()->refreshData("MFResetPasswordVisible"); - + connect(KeyboardMonitor::instance(), &KeyboardMonitor::capsLockStatusChanged, m_passwordAuth, &AuthPassword::setCapsLockVisible); connect(m_passwordAuth, &AuthPassword::requestChangeFocus, this, &MFAWidget::updateFocusPosition); } @@ -298,17 +290,17 @@ void MFAWidget::initFingerprintAuth() { if (m_fingerprintAuth) { m_fingerprintAuth->reset(); - m_mainLayout->insertWidget(m_index, m_fingerprintAuth); + m_authLayout->insertWidget(m_index, m_fingerprintAuth); return; } m_fingerprintAuth = new AuthFingerprint(this); m_fingerprintAuth->setAuthFactorType(DDESESSIONCC::MultiAuthFactor); - m_mainLayout->insertWidget(m_index, m_fingerprintAuth); + m_authLayout->insertWidget(m_index, m_fingerprintAuth); connect(m_fingerprintAuth, &AuthFingerprint::activeAuth, this, [this] { emit requestStartAuthentication(m_model->currentUser()->name(), AT_Fingerprint); }); - connect(m_fingerprintAuth, &AuthFingerprint::authFinished, this, [this](const int value) { + connect(m_fingerprintAuth, &AuthFingerprint::authFinished, this, [this](const AuthState value) { checkAuthResult(AT_Fingerprint, value); }); } @@ -320,12 +312,13 @@ void MFAWidget::initUKeyAuth() { if (m_ukeyAuth) { m_ukeyAuth->reset(); - m_mainLayout->insertWidget(m_index, m_ukeyAuth); + m_authLayout->insertWidget(m_index, m_ukeyAuth); return; } m_ukeyAuth = new AuthUKey(this); - m_ukeyAuth->setCapsLockVisible(m_capslockMonitor->isCapslockOn()); - m_mainLayout->insertWidget(m_index, m_ukeyAuth); + m_ukeyAuth->setCapsLockVisible(KeyboardMonitor::instance()->isCapsLockOn()); + m_ukeyAuth->setAuthStatueVisible(true); + m_authLayout->insertWidget(m_index, m_ukeyAuth); connect(m_ukeyAuth, &AuthUKey::activeAuth, this, [this] { emit requestStartAuthentication(m_model->currentUser()->name(), AT_Ukey); @@ -341,22 +334,15 @@ void MFAWidget::initUKeyAuth() emit sendTokenToAuth(m_model->currentUser()->name(), AT_Ukey, text); }); connect(m_lockButton, &QPushButton::clicked, m_ukeyAuth, &AuthUKey::requestAuthenticate); - connect(m_ukeyAuth, &AuthUKey::authFinished, this, [this](const bool state) { + connect(m_ukeyAuth, &AuthUKey::authFinished, this, [this](const AuthState state) { checkAuthResult(AT_Ukey, state); }); - connect(m_capslockMonitor, &KeyboardMonitor::capslockStatusChanged, m_ukeyAuth, &AuthUKey::setCapsLockVisible); - - /* 输入框数据同步 */ - std::function PINChanged = std::bind(&MFAWidget::syncUKey, this, std::placeholders::_1); - m_registerFunctions["MFUKeyAuth"] = FrameDataBind::Instance()->registerFunction("MFUKeyAuth", PINChanged); + connect(KeyboardMonitor::instance(), &KeyboardMonitor::capsLockStatusChanged, m_ukeyAuth, &AuthUKey::setCapsLockVisible); connect(m_ukeyAuth, &AuthUKey::lineEditTextChanged, this, [this](const QString &value) { - FrameDataBind::Instance()->updateValue("MFUKeyAuth", value); if (m_model->getAuthProperty().PINLen > 0 && value.size() >= m_model->getAuthProperty().PINLen) { emit m_ukeyAuth->requestAuthenticate(); } }); - FrameDataBind::Instance()->refreshData("MFUKeyAuth"); - connect(m_ukeyAuth, &AuthUKey::requestChangeFocus, this, &MFAWidget::updateFocusPosition); } @@ -367,17 +353,17 @@ void MFAWidget::initFaceAuth() { if (m_faceAuth) { m_faceAuth->reset(); - m_mainLayout->insertWidget(m_index, m_faceAuth); + m_authLayout->insertWidget(m_index, m_faceAuth); return; } m_faceAuth = new AuthFace(this); m_faceAuth->setAuthFactorType(DDESESSIONCC::MultiAuthFactor); - m_mainLayout->insertWidget(m_index, m_faceAuth); + m_authLayout->insertWidget(m_index, m_faceAuth); connect(m_faceAuth, &AuthFace::activeAuth, this, [this] { emit requestStartAuthentication(m_model->currentUser()->name(), AT_Face); }); - connect(m_faceAuth, &AuthFace::authFinished, this, [this](const bool state) { + connect(m_faceAuth, &AuthFace::authFinished, this, [this](const AuthState state) { checkAuthResult(AT_Face, state); }); } @@ -389,28 +375,63 @@ void MFAWidget::initIrisAuth() { if (m_irisAuth) { m_irisAuth->reset(); - m_mainLayout->insertWidget(m_index, m_irisAuth); + m_authLayout->insertWidget(m_index, m_irisAuth); return; } m_irisAuth = new AuthIris(this); m_irisAuth->setAuthFactorType(DDESESSIONCC::MultiAuthFactor); - m_mainLayout->insertWidget(m_index, m_irisAuth); + m_authLayout->insertWidget(m_index, m_irisAuth); connect(m_irisAuth, &AuthIris::activeAuth, this, [this] { emit requestStartAuthentication(m_model->currentUser()->name(), AT_Iris); }); - connect(m_irisAuth, &AuthIris::authFinished, this, [this](const bool state) { + connect(m_irisAuth, &AuthIris::authFinished, this, [this](const AuthState state) { checkAuthResult(AT_Iris, state); }); } +/** + * @brief 由插件加载,无法加载时,结束该认证 + */ +void MFAWidget::initGestureAuth() +{ + if (m_gestureAuth) { + return; + } + + auto plugin = PluginManager::instance()->getLoginPlugin(AuthType::AT_Pattern); + if (!plugin) { + // 如果插件不存在或被析构,次序控制将结束已开启的认证 + MFASequenceControl::instance().insertIsolateAuthWidget(AT_Pattern, nullptr); + qCWarning(DDE_SHELL) << "Pattern plug not found, should stop pattern auth"; + return; + } + + m_gestureAuth = new AuthCustom(this, AuthType::AT_Pattern); + m_gestureAuth->setModule(plugin); + m_gestureAuth->setModel(m_model); + m_gestureAuth->initUi(); + m_gestureAuth->reset(); + m_gestureAuth->hide(); + + connect(m_gestureAuth, &AuthCustom::requestSendToken, this, [this](const QString &token) { + Q_EMIT sendTokenToAuth(m_model->currentUser()->name(), AuthType::AT_Pattern, token); + }); + + connect(m_gestureAuth, &AuthCustom::activeAuth, this, [this] { + Q_EMIT requestStartAuthentication(m_model->currentUser()->name(), AuthType::AT_Pattern); + }); + + MFASequenceControl::instance().insertIsolateAuthWidget(AT_Pattern, m_gestureAuth->getLoginPlugin()->content()); +} + /** * @brief 检查多因子认证结果 * * @param type * @param succeed */ -void MFAWidget::checkAuthResult(const int type, const int state) +void MFAWidget::checkAuthResult(const AuthType type, const AuthState state) { if (type == AT_Password && state == AS_Success) { if (m_fingerprintAuth && m_fingerprintAuth->authState() == AS_Locked) { @@ -465,8 +486,9 @@ void MFAWidget::updateFocusPosition() int MFAWidget::getTopSpacing() const { const int calcTopHeight = static_cast(topLevelWidget()->geometry().height() * AUTH_WIDGET_TOP_SPACING_PERCENT); - // 验证类型数量*高度 - const int authWidgetHeight = (m_index - 2) * 47 + MIN_AUTH_WIDGET_HEIGHT; + auto sequenceAuthWid = MFASequenceControl::instance().currentAuthWidget(); + // 验证类型数量*高度,或者是独立ui的高度 + const int authWidgetHeight = sequenceAuthWid == nullptr ? m_index * 47 + MIN_AUTH_WIDGET_HEIGHT : sequenceAuthWid->height(); // 当分辨率过低时,如果仍然保持用户头像到屏幕顶端的距离为屏幕高度的35%,那么验证窗口整体时偏下的。 // 计算当验证窗口居中时距离屏幕顶端的高度,与屏幕高度*0.35对比取较小值。 @@ -474,8 +496,23 @@ int MFAWidget::getTopSpacing() const const int topHeight = qMin(calcTopHeight, centerTop); // 需要额外增加的顶部间隔高度 = 屏幕高度*0.35 - 验证窗口高度 - 时间控件高度 - 布局间隔 - const int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT) - - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN); + const int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN); return qMax(15, deltaY); } + +/** + * @brief 根据认证序列,提供不同来源的UI + */ +QWidget *MFAWidget::getAuthWidget() +{ + auto wid = MFASequenceControl::instance().currentAuthWidget(); + return wid == nullptr ? this : wid; +} + +void MFAWidget::resizeEvent(QResizeEvent *event) +{ + QTimer::singleShot(0, this, &MFAWidget::updateBlurEffectGeometry); + + AuthWidget::resizeEvent(event); +} diff --git a/src/session-widgets/mfa_widget.h b/src/session-widgets/mfa_widget.h index 25d2cdc1..a216231d 100644 --- a/src/session-widgets/mfa_widget.h +++ b/src/session-widgets/mfa_widget.h @@ -1,23 +1,6 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef MFAWIDGET_H #define MFAWIDGET_H @@ -34,11 +17,16 @@ class MFAWidget : public AuthWidget explicit MFAWidget(QWidget *parent = nullptr); void setModel(const SessionBaseModel *model) override; - void setAuthType(const int type) override; - void setAuthState(const int type, const int state, const QString &message) override; + void setAuthType(const AuthCommon::AuthFlags type) override; + void setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) override; void autoUnlock(); int getTopSpacing() const override; + QWidget *getAuthWidget() override; + +protected: + void resizeEvent(QResizeEvent *event) override; + private: void initUI(); void initConnections(); @@ -48,14 +36,16 @@ class MFAWidget : public AuthWidget void initUKeyAuth(); void initFaceAuth(); void initIrisAuth(); + void initGestureAuth(); - void checkAuthResult(const int type, const int state) override; + void checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state) override; void updateFocusPosition(); private: int m_index; QVBoxLayout *m_mainLayout; + QVBoxLayout *m_authLayout; QList m_widgetList; }; diff --git a/src/session-widgets/mfasequencecontrol.cpp b/src/session-widgets/mfasequencecontrol.cpp new file mode 100644 index 00000000..007a798e --- /dev/null +++ b/src/session-widgets/mfasequencecontrol.cpp @@ -0,0 +1,252 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "mfasequencecontrol.h" +#include "dconfig_helper.h" +#include "authcommon.h" + +#include + +#include +#include +#include +#include +#include + +const QString kConfigAttrName = "mfaSequence"; +const QString kConfigUserKey = "userType"; +const QString kConfigAuthTypeKey = "authSequence"; +const QString kDefaultUser = "default"; +const QString kADDomainUser = "adDomain"; +const QString kNativeUser = "native"; +const QString kAllUser = "all"; + +// 不处理某个类型的认证过程,只处理UI切换 +MFASequenceControl::MFASequenceControl(QObject *parent) + : QObject(parent) + , m_userType("") + , m_authType(-1) + , m_configUserType("") + , m_currentType(-1) + , m_validConfig(false) +{ + initConfig(); + DConfigHelper::instance()->bind(this, kConfigAttrName, &MFASequenceControl::onPropertyChanged); +} + +MFASequenceControl &MFASequenceControl::instance() +{ + static MFASequenceControl control; + return control; +} + +// 外部设置当前认证类型 +// 工行在此判断是否多因和是否满足配置场景 +void MFASequenceControl::setAuthType(int type) +{ + qCDebug(DDE_SHELL) << "set mfa auth type" << type << this; + + // 先重置到默认界面上 + m_currentType = AuthCommon::AT_None; + Q_EMIT currentUIAuthTypeChanged(m_currentType); + + if (type == AuthCommon::AT_None) { + return; + } + + m_authType = type; + updateAuthSequence(); +} + +// 注意,同类型不代表同用户,所以设置后也需要更新 +void MFASequenceControl::setUserType(User::UserType type) +{ + qCDebug(DDE_SHELL) << "set mfa user type" << type << this; + + static QMap userTypes = { + {User::UserType::Default, kDefaultUser}, + {User::UserType::Native, kNativeUser}, + {User::UserType::ADDomain, kADDomainUser}}; + + m_userType = userTypes.value(type, kDefaultUser); +} + +int MFASequenceControl::currentAuthType() +{ + return m_currentType; +} + +void MFASequenceControl::insertIsolateAuthWidget(int type, QWidget *authWidget) +{ + m_isolateWidgets[type] = authWidget; +} + +void MFASequenceControl::removeAuthWidget(int type) +{ + m_isolateWidgets.remove(type); +} + +// 设计如下:这个类仅被动响应由配置指定的认证序列 +// 比如配置为[1,256], 刚以MFAWidget开始认证,当被通知认证1成功时,推出256认证的UI +// 因此这个函数只会当开始指定认证时返回非空值 +QWidget *MFASequenceControl::currentAuthWidget() +{ + return m_isolateWidgets.value(m_currentType, nullptr); +} + +void MFASequenceControl::doNextAuth(int finishedAuth) +{ + if (!m_configAuthList.size()) { + return; + } + + auto currentIndex = m_configAuthList.indexOf(finishedAuth); + if (currentIndex == -1) { + // 无法处理,认证类型有异常 + return; + } + + if (currentIndex == m_configAuthList.size() - 1) { + qCDebug(DDE_SHELL) << "mfa auth sequence done, continue to other auth"; + + m_currentType = AuthCommon::AT_None; + + // 是否所有认证已结束 + auto allFinishedType = 0; + foreach (auto type, m_configAuthList) { + allFinishedType |= type; + } + + // 存在配置外的认证,切回默认认证UI + if (allFinishedType != m_authType) { + Q_EMIT currentUIAuthTypeChanged(AuthCommon::AT_None); + } + + return; + } + + // 通知UI显示下一个类型的认证界面 + m_currentType = m_configAuthList.value(currentIndex + 1); + qCDebug(DDE_SHELL) << "next auth type" << m_currentType; + + Q_EMIT currentUIAuthTypeChanged(m_currentType); +} + +void MFASequenceControl::initConfig() +{ + m_validConfig = false; + m_configAuthList.clear(); + m_configUserType = ""; + + auto obj = DConfigHelper::instance()->getConfig(kConfigAttrName, "").toJsonObject(); + toLocalConfig(obj); +} + +// json转内部配置 +void MFASequenceControl::toLocalConfig(const QJsonObject &obj) +{ + if (!obj.contains(kConfigUserKey) || !obj.contains(kConfigAuthTypeKey)) { + return; + } + + // 处理用户类型 + auto nameType = obj[kConfigUserKey].toString(); + if (nameType.isEmpty()) { + return; + } + + m_configUserType = nameType; + // 处理认证顺序 + auto authTypeList = obj[kConfigAuthTypeKey].toArray().toVariantList(); + // 多因必然类型比2多 + if (authTypeList.size() < 2) { + return; + } + + foreach (auto type, authTypeList) { + m_configAuthList.push_back(type.toInt()); + } + + // 注意仅在完成配置后才设置true值 + m_validConfig = true; +} + +// 如果配置类型在传入的类型中 +// 先完成配置认证,再执行其它认证 +void MFASequenceControl::updateAuthSequence() +{ + if (!m_validConfig) { + qCDebug(DDE_SHELL) << "config not valid"; + return; + } + + // FIXME 工行上不关注用户类型,DA仅给域用户配置 + if (!m_authType) { + qCDebug(DDE_SHELL) << "not expect value"; + return; + } + + if (m_configUserType != m_userType && m_configUserType != kAllUser) { + return; + } + + auto isolateAuthList = m_isolateWidgets.keys(); + bool isolateActive = false; + foreach (auto isolate, isolateAuthList) { + if (isolate & m_authType) { + if (m_isolateWidgets.value(isolate, nullptr) != nullptr) { + isolateActive = true; + } + } + } + + // 没有参与认证的独立界面,由于认证未提供,将在认证开始后关闭 + if (!isolateActive) { + return; + } + + // 先完成配置的认证顺序 + m_currentType = m_configAuthList.value(0); + + qCDebug(DDE_SHELL) << "start from type" << m_currentType << m_configAuthList; + Q_EMIT currentUIAuthTypeChanged(m_currentType); +} + +void MFASequenceControl::onAuthStatusChanged(int type, int status, const QString &message) +{ + //仅用于参数对齐 + Q_UNUSED(message) + + if (!m_configAuthList.size()) { + return; + } + + switch (status) { + case AuthCommon::AS_Success: + if (type == AuthCommon::AT_All) { + return; + } else { + doNextAuth(type); + } + break; + case AuthCommon::AS_Started: + // 多因认证开启了手势,但是并没有安装插件 + if (m_isolateWidgets.contains(type) && m_isolateWidgets.value(type, nullptr) == nullptr) { + Q_EMIT requestEndUnsupportedAuth(type); + } + } +} + +// 在下一次认证过程中生效 +void MFASequenceControl::onPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + qCInfo(DDE_SHELL) << "DConfig property changed, key: " << key << ", value: " << value; + if (key == kConfigAttrName) { + obj->initConfig(); + } +} diff --git a/src/session-widgets/mfasequencecontrol.h b/src/session-widgets/mfasequencecontrol.h new file mode 100644 index 00000000..f1021f58 --- /dev/null +++ b/src/session-widgets/mfasequencecontrol.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef MFASEQUENCECONTROL_H +#define MFASEQUENCECONTROL_H + +#include "userinfo.h" + +#include +#include + +class MFASequenceControl : public QObject +{ + Q_OBJECT +public: + static MFASequenceControl &instance(); + void setAuthType(int); + void setUserType(User::UserType); + + // 外部传入widget,如果为空也代表认证无效 + // 内置认证不参与 + void insertIsolateAuthWidget(int, QWidget*); + + int currentAuthType(); + QWidget *currentAuthWidget(); + + void doNextAuth(int); + +public Q_SLOTS: + void initConfig(); + // 响应认证状态变化 + void onAuthStatusChanged(int, int, const QString &); + // 响应配置变化 + static void onPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); + +Q_SIGNALS: + // 当某个认证成功时,通知UI转到下一个认证 + void currentUIAuthTypeChanged(int); + + // 某个认证的UI不存在,通知结束该认证 + void requestEndUnsupportedAuth(int); + +private: + explicit MFASequenceControl(QObject *parent = nullptr); + + // 从dconf初始化,greeter与lock各持一份,区别配置 + void toLocalConfig(const QJsonObject &); + void updateAuthSequence(); + void removeAuthWidget(int); + +private: + // 外部设置当前用户与开启的认证类型 + QString m_userType; + int m_authType; + + // 实际配置值 + QString m_configUserType; + QList m_configAuthList; + + // 当前处理中的认证 + int m_currentType; + + // 配置可靠性 + bool m_validConfig; + + // 外部已注册的提供UI的认证 + QMap> m_isolateWidgets; +}; + +#endif // MFASEQUENCECONTROL_H diff --git a/src/session-widgets/pluginconfigmap.cpp b/src/session-widgets/pluginconfigmap.cpp new file mode 100644 index 00000000..a0f6e30a --- /dev/null +++ b/src/session-widgets/pluginconfigmap.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "pluginconfigmap.h" + +PluginConfigMap &PluginConfigMap::instance() +{ + static PluginConfigMap configStack; + return configStack; +} + +const PluginConfig *PluginConfigMap::getConfig() +{ + if (m_configs.size()) { + // always return the first one + // config should be unicon, plugins should remove itselfs' config when deactived or unloaded + return m_configs.begin().value(); + } + return nullptr; +} + +void PluginConfigMap::requestAddConfig(ConfigIndex index, const PluginConfig *config) +{ + if (!config) { + return; + } + + m_configs.insert(index, config); +} + +void PluginConfigMap::requestRemoveConfig(PluginConfigMap::ConfigIndex index) +{ + if (m_configs.find(index) != m_configs.end()) { + m_configs.remove(index); + } +} diff --git a/src/session-widgets/pluginconfigmap.h b/src/session-widgets/pluginconfigmap.h new file mode 100644 index 00000000..0561a666 --- /dev/null +++ b/src/session-widgets/pluginconfigmap.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PLUGIN_CONFIG_MAP_H +#define PLUGIN_CONFIG_MAP_H + +#include +#include + +// retirve some properties for lockcontent from plugins +class PluginConfig +{ +public: + PluginConfig() {} + virtual ~PluginConfig() {} + + // if false, switch user button would be hidden in base session window + // override if nesscessary + // defalut return true + // you should get correct config from plugin + virtual bool isUserSwitchButtonVisiable() const { return true; } +}; + +class PluginConfigMap +{ +public: + enum ConfigIndex { + FullManagePlugin, + Max = FullManagePlugin + }; + + ~PluginConfigMap() {} + + static PluginConfigMap &instance(); + const PluginConfig *getConfig(); + +public slots: + void requestAddConfig(ConfigIndex index, const PluginConfig *); + void requestRemoveConfig(ConfigIndex); + +private: + QMap m_configs; + PluginConfigMap() {} + PluginConfigMap(const PluginConfigMap &); + PluginConfigMap &operator=(const PluginConfigMap &); +}; + +#endif // PLUGIN_CONFIG_MAP_H diff --git a/src/session-widgets/sessionbasemodel.cpp b/src/session-widgets/sessionbasemodel.cpp index e25ae262..b7f09194 100644 --- a/src/session-widgets/sessionbasemodel.cpp +++ b/src/session-widgets/sessionbasemodel.cpp @@ -1,12 +1,16 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "sessionbasemodel.h" +#include "dconfig_helper.h" +#include "dbus/dbusdisplaymanager.h" +#include "mfasequencecontrol.h" #include - #include -#include -#define SessionManagerService "com.deepin.SessionManager" -#define SessionManagerPath "/com/deepin/SessionManager" +#include "dbusconstant.h" DCORE_USE_NAMESPACE @@ -19,7 +23,6 @@ SessionBaseModel::SessionBaseModel(QObject *parent) , m_allowShowUserSwitchButton(false) , m_alwaysShowUserSwitchButton(false) , m_abortConfirm(false) - , m_isLockNoPassword(false) , m_isBlackMode(false) , m_isHibernateMode(false) , m_allowShowCustomUser(false) @@ -27,13 +30,25 @@ SessionBaseModel::SessionBaseModel(QObject *parent) , m_isUseWayland(QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) , m_appType(AuthCommon::None) , m_currentUser(nullptr) - , m_lastLogoutUser(nullptr) , m_powerAction(PowerAction::RequireNormal) , m_currentModeState(ModeStatus::NoStatus) - , m_authProperty {false, false, Unavailable, AuthCommon::None, AuthCommon::None, 0, "", "", ""} + , m_authProperty {false, false, Unavailable, AuthCommon::AT_None, AuthCommon::None, 0, "", "", ""} , m_users(new QMap>()) , m_loginedUsers(new QMap>()) -{ + , m_updatePowerMode(UPM_None) + , m_currentContentType(NoContent) + , m_lightdmPamStarted(false) + , m_authResult{AuthType::AT_None, AuthState::AS_None, ""} + , m_enableShellBlackMode(DConfigHelper::instance()->getConfig("enableShellBlack", true).toBool()) + , m_enableShutdownBlackWidget(DConfigHelper::instance()->getConfig("enableShutdownBlackWidget", true).toBool()) + , m_visibleShutdownWhenRebootOrShutdown(DConfigHelper::instance()->getConfig("visibleShutdownWhenRebootOrShutdown", true).toBool()) + , m_gsCheckpwd(false) +{ +#ifndef ENABLE_DSS_SNIPE + if (QGSettings::isSchemaInstalled("com.deepin.dde.power")) { + m_powerGsettings = new QGSettings("com.deepin.dde.power", "/com/deepin/dde/power/", this); + } +#endif } SessionBaseModel::~SessionBaseModel() @@ -42,6 +57,17 @@ SessionBaseModel::~SessionBaseModel() delete m_loginedUsers; } +#ifndef ENABLE_DSS_SNIPE +QVariant SessionBaseModel::getPowerGSettings(const QString &node, const QString &key) +{ + QVariant value = valueByQSettings(node, key, true); + if (m_powerGsettings != nullptr && m_powerGsettings->keys().contains(key)) { + value = m_powerGsettings->get(key); + } + return value; +} +#endif + std::shared_ptr SessionBaseModel::findUserByUid(const uint uid) const { for (auto user : qAsConst(*m_users)) { @@ -66,6 +92,11 @@ std::shared_ptr SessionBaseModel::findUserByName(const QString &name) cons return std::shared_ptr(nullptr); } +std::shared_ptr SessionBaseModel::findUserByPath(const QString &path) const +{ + return m_users->value(path, std::shared_ptr(nullptr)); +} + void SessionBaseModel::setAppType(const AppType type) { m_appType = type; @@ -73,7 +104,7 @@ void SessionBaseModel::setAppType(const AppType type) void SessionBaseModel::setSessionKey(const QString &sessionKey) { - qDebug("set session key: %s", qPrintable(sessionKey)); + qCInfo(DDE_SHELL) << "Set session key:" << sessionKey; if (m_sessionKey == sessionKey) return; @@ -85,19 +116,22 @@ void SessionBaseModel::setSessionKey(const QString &sessionKey) void SessionBaseModel::setPowerAction(const PowerAction &powerAction) { - qDebug("set power action: %d", powerAction); + qCInfo(DDE_SHELL) << "Incoming action:" << powerAction << ", current action:" << m_powerAction; if (powerAction == m_powerAction) return; m_powerAction = powerAction; + if (m_enableShutdownBlackWidget && !gsCheckpwd() && (powerAction == SessionBaseModel::PowerAction::RequireRestart || powerAction == SessionBaseModel::PowerAction::RequireShutdown)) + Q_EMIT shutdownkModeChanged(true); + emit onPowerActionChanged(powerAction); } void SessionBaseModel::setCurrentModeState(const ModeStatus ¤tModeState) { - qDebug("set current mode state: %d", currentModeState); + qCInfo(DDE_SHELL) << "Incoming state:" << currentModeState << ", current state:" << m_currentModeState; if (m_currentModeState == currentModeState) return; @@ -130,6 +164,7 @@ void SessionBaseModel::setHasVirtualKB(bool hasVirtualKB) void SessionBaseModel::setHasSwap(bool hasSwap) { + qCInfo(DDE_SHELL) << "Has swap:" << hasSwap; if (m_hasSwap == hasSwap) return; @@ -145,7 +180,7 @@ void SessionBaseModel::setHasSwap(bool hasSwap) */ void SessionBaseModel::setVisible(const bool visible) { - qDebug() << "set visible: " << visible; + qCInfo(DDE_SHELL) << "Set visible:" << visible << ", current visible:" << m_visible; if (m_visible == visible) { return; @@ -160,6 +195,7 @@ void SessionBaseModel::setVisible(const bool visible) void SessionBaseModel::setCanSleep(bool canSleep) { + qCInfo(DDE_SHELL) << "Can sleep:" << canSleep; if (m_canSleep == canSleep) return; @@ -199,6 +235,10 @@ void SessionBaseModel::setAbortConfirm(bool abortConfirm) void SessionBaseModel::setIsBlackMode(bool is_black) { + if (!m_enableShellBlackMode) { + return; + } + if (m_isBlackMode == is_black) return; @@ -206,21 +246,21 @@ void SessionBaseModel::setIsBlackMode(bool is_black) emit blackModeChanged(is_black); } -void SessionBaseModel::setIsHibernateModel(bool is_Hibernate) +void SessionBaseModel::setShutdownMode(bool is_black) { - if (m_isHibernateMode == is_Hibernate) + if (!m_enableShutdownBlackWidget || gsCheckpwd()) { return; - - m_isHibernateMode = is_Hibernate; - emit HibernateModeChanged(is_Hibernate); + } + Q_EMIT shutdownkModeChanged(is_black); } -void SessionBaseModel::setIsCheckedInhibit(bool checked) +void SessionBaseModel::setIsHibernateModel(bool is_Hibernate) { - if (m_isCheckedInhibit == checked) + if (m_isHibernateMode == is_Hibernate) return; - m_isCheckedInhibit = checked; + m_isHibernateMode = is_Hibernate; + emit HibernateModeChanged(is_Hibernate); } /** @@ -241,13 +281,12 @@ void SessionBaseModel::setAllowShowCustomUser(const bool allowShowCustomUser) * * @param type */ -void SessionBaseModel::setAuthType(const int type) +void SessionBaseModel::setAuthType(const AuthFlags type) { - qDebug("set auth type: %d", type); - - if (type == m_authProperty.AuthType) { + if (type == m_authProperty.AuthType && type != AT_None) { return; } + if (m_currentUser->type() == User::Default) { m_authProperty.AuthType = type; emit authTypeChanged(AT_None); @@ -264,7 +303,7 @@ void SessionBaseModel::setAuthType(const int type) */ void SessionBaseModel::addUser(const QString &path) { - qDebug("add user, path: %s", qPrintable(path)); + qDebug("Add user, path: %s", qPrintable(path)); if (m_users->contains(path)) { return; @@ -282,7 +321,7 @@ void SessionBaseModel::addUser(const QString &path) */ void SessionBaseModel::addUser(const std::shared_ptr user) { - qDebug("add user, path: %s, name: %s", qPrintable(user->path()), qPrintable(user->name())); + qInfo("Add user, path: %s, name: %s", qPrintable(user->path()), qPrintable(user->name())); const QList> userList = m_users->values(); if (userList.contains(user)) { @@ -316,7 +355,7 @@ void SessionBaseModel::removeUser(const QString &path) */ void SessionBaseModel::removeUser(const std::shared_ptr user) { - qDebug("remove user, name: %s, id: %d", qPrintable(user->name()), user->uid()); + qInfo("Remove user, name: %s, id: %d", qPrintable(user->name()), user->uid()); const QList> userList = m_users->values(); if (!userList.contains(user)) { @@ -341,7 +380,7 @@ std::shared_ptr SessionBaseModel::json2User(const QString &userJson) QJsonParseError jsonParseError; const QJsonDocument userDoc = QJsonDocument::fromJson(userJson.toUtf8(), &jsonParseError); if (jsonParseError.error != QJsonParseError::NoError || userDoc.isEmpty()) { - qWarning("failed to obtain current user information from LockService!"); + qWarning("Failed to obtain current user information from lock service!"); return user_ptr; } @@ -352,8 +391,10 @@ std::shared_ptr SessionBaseModel::json2User(const QString &userJson) const uid_t uid = static_cast(userObj["Uid"].toInt()); user_ptr = findUserByUid(uid); } - if (user_ptr) - user_ptr->setLastAuthType(userObj["AuthType"].toInt()); + if (user_ptr) { + user_ptr->setLastAuthType(AUTH_TYPE_CAST(userObj["AuthType"].toInt())); + user_ptr->setLastCustomAuth(userObj["LastCustomAuth"].toString()); + } return user_ptr; } @@ -366,11 +407,14 @@ std::shared_ptr SessionBaseModel::json2User(const QString &userJson) */ bool SessionBaseModel::updateCurrentUser(const QString &userJson) { - qDebug("update current user, data: %s", qPrintable(userJson)); - + qCInfo(DDE_SHELL) << "Update current user:" << userJson; std::shared_ptr user_ptr = json2User(userJson); - if (!user_ptr) - user_ptr = m_lastLogoutUser ? m_lastLogoutUser : m_users->first(); + if (!user_ptr) { + if (m_currentUser || m_users->isEmpty()) + return false; + + user_ptr = m_users->first(); + } return updateCurrentUser(user_ptr); } @@ -384,13 +428,15 @@ bool SessionBaseModel::updateCurrentUser(const QString &userJson) bool SessionBaseModel::updateCurrentUser(const std::shared_ptr user) { if (!user) { - qWarning() << "Failed to set current user!" << user.get(); + qCWarning(DDE_SHELL) << "Failed to set current user!" << user.get(); return false; } - qDebug() << "SessionBaseModel::updateCurrentUser:" << user->name(); + qCInfo(DDE_SHELL) << "Update current user:" << user->name(); if (m_currentUser && *m_currentUser == *user) { + qCWarning(DDE_SHELL) << "Same user to be updated" << user.get(); + m_currentUser->updateUserInfo(); return false; } @@ -407,8 +453,7 @@ bool SessionBaseModel::updateCurrentUser(const std::shared_ptr user) */ void SessionBaseModel::updateUserList(const QStringList &list) { - qDebug() << "update user list: " << list; - + qCInfo(DDE_SHELL) << "Update user list: " << list; QStringList listTmp = m_users->keys(); for (const QString &path : list) { if (m_users->contains(path)) { @@ -424,38 +469,6 @@ void SessionBaseModel::updateUserList(const QStringList &list) emit userListChanged(m_users->values()); } -/** - * @brief 更新上一个登录用户 - * - * @param uid - */ -void SessionBaseModel::updateLastLogoutUser(const uid_t uid) -{ - qDebug() << "SessionBaseModel::updateLastLogoutUser:" << uid; - QList> userList = m_users->values(); - auto it = std::find_if(userList.begin(), userList.end(), [uid](std::shared_ptr &user) { - return user->uid() == uid; - }); - if (it != userList.end()) { - updateLastLogoutUser(it.i->t()); - } -} - -/** - * @brief 设置上一个登录的用户 - * - * @param lastLogoutUser - */ -void SessionBaseModel::updateLastLogoutUser(const std::shared_ptr lastLogoutUser) -{ - if (!lastLogoutUser.get() || m_lastLogoutUser == lastLogoutUser) { - return; - } - qInfo() << "last logout user:" << lastLogoutUser->name() << lastLogoutUser->uid(); - - m_lastLogoutUser = lastLogoutUser; -} - /** * @brief 更新已登录用户列表 * @@ -463,13 +476,29 @@ void SessionBaseModel::updateLastLogoutUser(const std::shared_ptr lastLogo */ void SessionBaseModel::updateLoginedUserList(const QString &list) { - qDebug() << "update logined user list: " << list; + qCDebug(DDE_SHELL) << "Logined user list: " << list; + // kwin崩溃时systemd中的sessions不会被remove掉,这里通过DisplayManager的session信息过滤一遍(临时解决方案) + QStringList loggedUserNameList; + DBusDisplayManager displayManager("org.freedesktop.DisplayManager", "/org/freedesktop/DisplayManager", QDBusConnection::systemBus()); + const auto &sessions = displayManager.sessions(); + for (const auto &session : sessions) { + const QString &sessionPath = session.path(); + if (sessionPath.isEmpty()) + continue; + QDBusInterface interface("org.freedesktop.DisplayManager", sessionPath, "org.freedesktop.DisplayManager.Session", QDBusConnection::systemBus()); + if (interface.isValid()) { + const QString &userName = interface.property("UserName").toString(); + if (!userName.isEmpty()) + loggedUserNameList.append(userName); + } + } + qInfo(DDE_SHELL) << "Logined users from display manager: " << loggedUserNameList; QList loginedUsersTmp = m_loginedUsers->keys(); QJsonParseError jsonParseError; const QJsonDocument loginedUserListDoc = QJsonDocument::fromJson(list.toUtf8(), &jsonParseError); if (jsonParseError.error != QJsonParseError::NoError) { - qWarning("The logined user list is wrong!"); + qCWarning(DDE_SHELL) << "The logined user list is wrong!"; return; } const QJsonObject loginedUserListDocObj = loginedUserListDoc.object(); @@ -483,13 +512,16 @@ void SessionBaseModel::updateLoginedUserList(const QString &list) // 排除非正常登录用户 continue; } - const QString path = QString("/com/deepin/daemon/Accounts/User") + QString::number(uid); + const QString path = QString(DSS_DBUS::accountsUserPath).arg(QString::number(uid)); if (!m_loginedUsers->contains(path)) { // 对于通过自定义窗口输入的账户(域账户), 此时账户还没添加进来,导致下面m_users->value(path)为空指针,调用会导致程序奔溃 // 因此在登录时,对于新增的账户,调用addUser先将账户添加进来,然后再去更新对应账户的登录状态 addUser(path); - m_loginedUsers->insert(path, m_users->value(path)); - m_users->value(path)->updateLoginState(true); + auto user = m_users->value(path); + if (user->name().isEmpty() || loggedUserNameList.contains(user->name())) { + m_loginedUsers->insert(path, user); + user->updateLoginState(true); + } } else { loginedUsersTmp.removeAll(path); } @@ -500,7 +532,7 @@ void SessionBaseModel::updateLoginedUserList(const QString &list) m_users->value(path)->updateLoginState(false); } - qInfo() << "Logined users: " << m_loginedUsers->keys(); + qCInfo(DDE_SHELL) << "Logined users: " << m_loginedUsers->keys(); emit loginedUserListChanged(m_loginedUsers->values()); } @@ -511,8 +543,6 @@ void SessionBaseModel::updateLoginedUserList(const QString &list) */ void SessionBaseModel::updateLimitedInfo(const QString &info) { - qDebug("update limit info: %s", qPrintable(info)); - m_currentUser->updateLimitsInfo(info); } @@ -523,7 +553,7 @@ void SessionBaseModel::updateLimitedInfo(const QString &info) */ void SessionBaseModel::updateFrameworkState(const int state) { - qDebug("update framework state: %d", state); + qCInfo(DDE_SHELL) << "Deepin authenticate framework state:" << state; if (state == m_authProperty.FrameworkState) { return; @@ -551,6 +581,7 @@ void SessionBaseModel::updateSupportedMixAuthFlags(const int flags) */ void SessionBaseModel::updateSupportedEncryptionType(const QString &type) { + qCInfo(DDE_SHELL) << "Support encryption type:" << type; if (type == m_authProperty.EncryptionType) return; @@ -577,8 +608,6 @@ void SessionBaseModel::updateFuzzyMFA(const bool fuzzMFA) */ void SessionBaseModel::updateMFAFlag(const bool MFAFlag) { - qDebug() << "update MFA flag: " << MFAFlag; - if (MFAFlag == m_authProperty.MFAFlag) return; @@ -618,12 +647,12 @@ void SessionBaseModel::updatePrompt(const QString &prompt) */ void SessionBaseModel::updateFactorsInfo(const MFAInfoList &infoList) { - qDebug() << "update factors info: " << infoList; + qCInfo(DDE_SHELL) << "Factors info:" << infoList; m_authProperty.AuthType = AT_None; switch (m_authProperty.FrameworkState) { case Available: for (const MFAInfo &info : infoList) { - m_authProperty.AuthType |= info.AuthType; + m_authProperty.AuthType |= AUTH_FLAGS_CAST(info.AuthType); } emit authTypeChanged(m_authProperty.AuthType); break; @@ -641,9 +670,11 @@ void SessionBaseModel::updateFactorsInfo(const MFAInfoList &infoList) * @param state * @param result */ -void SessionBaseModel::updateAuthState(const int type, const int state, const QString &message) +void SessionBaseModel::updateAuthState(const AuthType type, const AuthState state, const QString &message) { - qDebug("update auth state, type: %d, state: %d, result: %s", type, state, qPrintable(message)); + m_authResult.authState = state; + m_authResult.authType = type; + m_authResult.authMessage = message; switch (m_authProperty.FrameworkState) { case Available: @@ -654,3 +685,64 @@ void SessionBaseModel::updateAuthState(const int type, const int state, const QS break; } } + +bool SessionBaseModel::isLightdmPamStarted() const +{ + return m_lightdmPamStarted; +} + +void SessionBaseModel::setLightdmPamStarted(bool lightdmPamStarted) +{ + if(m_lightdmPamStarted != lightdmPamStarted){ + m_lightdmPamStarted = lightdmPamStarted; + if(lightdmPamStarted){ + Q_EMIT lightdmPamStartedChanged(); + } + } +} + +void SessionBaseModel::setTerminalLocked(bool locked) +{ + if (locked == m_isTerminalLocked) + return; + + m_isTerminalLocked = locked; + emit terminalLockedChanged(locked); +} + +void SessionBaseModel::sendTerminalLockedSignal() +{ + emit terminalLockedChanged(m_isTerminalLocked); +} + +void SessionBaseModel::setUserlistVisible(bool visible) +{ + if (visible == m_userlistVisible) { + return; + } + m_userlistVisible = visible; +} + +void SessionBaseModel::setQuickLoginProcess(bool val) +{ + m_isQuickLoginProcess = val; +} + +void SessionBaseModel::setGsCheckpwd(bool value) +{ + if (m_gsCheckpwd != value) { + m_gsCheckpwd = value; + } +} + +bool SessionBaseModel::isNoPasswordLogin() const +{ + // 检查当前用户是否存在 + if (!m_currentUser) { + qCWarning(DDE_SHELL) << "Current user is null"; + return false; + } + + // 直接调用当前用户的isNoPasswordLogin方法 + return m_currentUser->isNoPasswordLogin(); +} \ No newline at end of file diff --git a/src/session-widgets/sessionbasemodel.h b/src/session-widgets/sessionbasemodel.h index d5ef39b6..784c7c61 100644 --- a/src/session-widgets/sessionbasemodel.h +++ b/src/session-widgets/sessionbasemodel.h @@ -1,12 +1,19 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef SESSIONBASEMODEL_H #define SESSIONBASEMODEL_H #include "authcommon.h" #include "userinfo.h" -#include - #include +#ifndef ENABLE_DSS_SNIPE +#include +#else +#include +#endif #include #include @@ -26,6 +33,8 @@ class SessionBaseModel : public QObject enum PowerAction { None, RequireNormal, + RequireUpdateShutdown, + RequireUpdateRestart, RequireShutdown, RequireRestart, RequireSuspend, @@ -45,16 +54,33 @@ class SessionBaseModel : public QObject SessionMode, PowerMode, ShutDownMode, - ResetPasswdMode + ResetPasswdMode, + UpdateMode, + SelectSameNameUserMode, }; Q_ENUM(ModeStatus) + enum UpdatePowerMode { + UPM_None, + UPM_UpdateAndShutdown, + UPM_UpdateAndReboot + }; + Q_ENUM(UpdatePowerMode) + + enum ContentType { + NoContent, + WarningContent, + LockContent, + UpdateContent + }; + Q_ENUM(ContentType) + /* com.deepin.daemon.Authenticate */ struct AuthProperty { bool FuzzyMFA; // Reserved bool MFAFlag; // 多因子标志位 int FrameworkState; // 认证框架是否可用标志位 - int AuthType; // 账户开启的认证类型 + AuthFlags AuthType; // 账户开启的认证类型 int MixAuthFlags; // 受支持的认证类型 int PINLen; // PIN 码的最大长度 QString EncryptionType; // 加密类型 @@ -62,17 +88,23 @@ class SessionBaseModel : public QObject QString UserName; // 账户名 }; + struct AuthResult { + AuthType authType; // 认证结果对应的认证类型,AT_ALL时代表所有认证类型 + AuthState authState; // 认证结果 + QString authMessage; // 认证消息 + }; + explicit SessionBaseModel(QObject *parent = nullptr); ~SessionBaseModel() override; inline std::shared_ptr currentUser() const { return m_currentUser; } - inline std::shared_ptr lastLogoutUser() const { return m_lastLogoutUser; } inline QList> loginedUserList() const { return m_loginedUsers->values(); } inline QList> userList() const { return m_users->values(); } std::shared_ptr findUserByUid(const uint uid) const; std::shared_ptr findUserByName(const QString &name) const; + std::shared_ptr findUserByPath(const QString &path) const; inline AppType appType() const { return m_appType; } void setAppType(const AppType type); @@ -120,22 +152,49 @@ class SessionBaseModel : public QObject inline bool isBlackMode() const { return m_isBlackMode; } void setIsBlackMode(bool is_black); + void setShutdownMode(bool is_black); + inline bool isHibernateMode() const { return m_isHibernateMode; } void setIsHibernateModel(bool is_Hibernate); - inline bool isCheckedInhibit() const { return m_isCheckedInhibit; } - void setIsCheckedInhibit(bool checked); - inline bool allowShowCustomUser() const { return m_allowShowCustomUser; } void setAllowShowCustomUser(const bool allowShowCustomUser); inline const QList> getUserList() const { return m_users->values(); } inline const AuthProperty &getAuthProperty() const { return m_authProperty; } - void setAuthType(const int type); + void setAuthType(const AuthFlags type); std::shared_ptr json2User(const QString &userJson); + void setUpdatePowerMode(UpdatePowerMode mode) { m_updatePowerMode = mode; } + UpdatePowerMode updatePowerMode() const { return m_updatePowerMode; } + void setTerminalLocked(bool locked); + inline bool terminalLocked() const { return m_isTerminalLocked; } + void sendTerminalLockedSignal(); + + void setCurrentContentType(ContentType type) { m_currentContentType = type; } + ContentType currentContentType() const { return m_currentContentType; } + + bool isLightdmPamStarted() const; + void setLightdmPamStarted(bool lightPamStarted); + + inline bool visibleShutdownWhenRebootOrShutdown() const { return m_visibleShutdownWhenRebootOrShutdown; } + + inline const AuthResult &getAuthResult() const { return m_authResult; } + + inline bool userlistVisible() const { return m_userlistVisible; } + void setUserlistVisible(bool visible); + + inline bool isQuickLoginProcess() const { return m_isQuickLoginProcess; } + void setQuickLoginProcess(bool ); + + inline bool gsCheckpwd() const { return m_gsCheckpwd; } + void setGsCheckpwd(bool value); + + // 检查当前用户是否设置了免密登录 + bool isNoPasswordLogin() const; + signals: /* com.deepin.daemon.Accounts */ void currentUserChanged(const std::shared_ptr); @@ -147,6 +206,8 @@ class SessionBaseModel : public QObject void MFAFlagChanged(const bool); /* others */ void visibleChanged(const bool); + //通知前端lightdm pam 已经开启 + void lightdmPamStartedChanged(); public slots: /* com.deepin.daemon.Accounts */ @@ -157,8 +218,6 @@ public slots: bool updateCurrentUser(const QString &userJson); bool updateCurrentUser(const std::shared_ptr user); void updateUserList(const QStringList &list); - void updateLastLogoutUser(const uid_t uid); - void updateLastLogoutUser(const std::shared_ptr lastLogoutUser); void updateLoginedUserList(const QString &list); /* com.deepin.daemon.Authenticate */ void updateLimitedInfo(const QString &info); @@ -166,24 +225,30 @@ public slots: void updateSupportedMixAuthFlags(const int flags); void updateSupportedEncryptionType(const QString &type); /* com.deepin.daemon.Authenticate.Session */ - void updateAuthState(const int type, const int state, const QString &message); + void updateAuthState(const AuthType type, const AuthState state, const QString &message); void updateFactorsInfo(const MFAInfoList &infoList); void updateFuzzyMFA(const bool fuzzMFA); void updateMFAFlag(const bool MFAFlag); void updatePINLen(const int PINLen); void updatePrompt(const QString &prompt); +#ifndef ENABLE_DSS_SNIPE + QVariant getPowerGSettings(const QString &node, const QString &key); +#endif signals: void authTipsMessage(const QString &message, AuthFailedType type = KEYBOARD); void authFailedMessage(const QString &message, AuthFailedType type = KEYBOARD); void authFailedTipsMessage(const QString &message, AuthFailedType type = KEYBOARD); void authFinished(bool success); + void accountError(); + void checkAccountFinished(); void onPowerActionChanged(PowerAction poweraction); void onRequirePowerAction(PowerAction poweraction, bool needConfirm); void onSessionKeyChanged(const QString &sessionKey); void showUserList(); void showLockScreen(); void showShutdown(); + void showUpdate(bool doReboot); void onStatusChanged(ModeStatus status); void onUserListChanged(QList> list); void hasVirtualKBChanged(bool hasVirtualKB); @@ -195,15 +260,30 @@ public slots: void userListLoginedChanged(QList> list); void activeAuthChanged(bool active); void blackModeChanged(bool is_black); + void shutdownkModeChanged(bool is_black); void HibernateModeChanged(bool is_hibernate); //休眠信号改变 void prepareForSleep(bool is_Sleep); //待机信号改变 void shutdownInhibit(const SessionBaseModel::PowerAction action, bool needConfirm); - void cancelShutdownInhibit(); void tipsShowed(); void clearServerLoginWidgetContent(); - void authStateChanged(const int, const int, const QString &); - void authTypeChanged(const int type); + void authStateChanged(const AuthType, const AuthState, const QString &); + void authTypeChanged(const AuthFlags type); + + // 关闭插件右键菜单信号 + void hidePluginMenu(); + void terminalLockedChanged(bool isLocked); + +protected: + template + T valueByQSettings(const QString & group, + const QString & key, + const QVariant &failback) { + return findValueByQSettings(DDESESSIONCC::session_ui_configs, + group, + key, + failback); + } private: bool m_hasSwap; @@ -213,25 +293,37 @@ public slots: bool m_allowShowUserSwitchButton; bool m_alwaysShowUserSwitchButton; bool m_abortConfirm; - bool m_isLockNoPassword; bool m_isBlackMode; bool m_isHibernateMode; - bool m_isLock = false; bool m_allowShowCustomUser; bool m_SEOpen; // 保存等保开启、关闭的状态 bool m_isUseWayland; int m_userListSize = 0; + bool m_isTerminalLocked = false; + bool m_userlistVisible = true; AppType m_appType; QList> m_userList; std::shared_ptr m_currentUser; - std::shared_ptr m_lastLogoutUser; QString m_sessionKey; PowerAction m_powerAction; ModeStatus m_currentModeState; - bool m_isCheckedInhibit = false; AuthProperty m_authProperty; // 认证相关属性的值,初始时通过dbus获取,暂存在model中,供widget初始化界面使用 QMap> *m_users; QMap> *m_loginedUsers; + UpdatePowerMode m_updatePowerMode; + ContentType m_currentContentType; +#ifndef ENABLE_DSS_SNIPE + QGSettings* m_powerGsettings = nullptr; +#else + Dtk::Core::DConfig *m_powerConfig = nullptr; +#endif + bool m_lightdmPamStarted; // 标志lightdmpam是否已经开启,主要用于greeter,lock不涉及lightdm + AuthResult m_authResult; // 记录认证结果 + bool m_enableShellBlackMode; + bool m_enableShutdownBlackWidget; + bool m_visibleShutdownWhenRebootOrShutdown; + bool m_isQuickLoginProcess=false;//标志当前界面展示是否为快速登录流程 + bool m_gsCheckpwd; }; #endif // SESSIONBASEMODEL_H diff --git a/src/session-widgets/sessionbasewindow.cpp b/src/session-widgets/sessionbasewindow.cpp index d1494cf0..70048c2a 100644 --- a/src/session-widgets/sessionbasewindow.cpp +++ b/src/session-widgets/sessionbasewindow.cpp @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "sessionbasewindow.h" #include "constants.h" +#include "centertopwidget.h" #include #include @@ -7,6 +12,8 @@ using namespace DDESESSIONCC; +const int kDefaultWidgetIndex = 0; + SessionBaseWindow::SessionBaseWindow(QWidget *parent) : QFrame(parent) , m_centerTopFrame(nullptr) @@ -25,6 +32,7 @@ SessionBaseWindow::SessionBaseWindow(QWidget *parent) , m_centerBottomWidget(nullptr) , m_rightBottomWidget(nullptr) , m_centerSpacerItem(new QSpacerItem(0, 0)) + , m_stackedLayout(nullptr) { initUI(); } @@ -58,7 +66,7 @@ void SessionBaseWindow::setRightBottomWidget(QWidget * const widget) m_rightBottomWidget = widget; } -void SessionBaseWindow::setCenterContent(QWidget * const widget, Qt::AlignmentFlag align, int spacerHeight) +void SessionBaseWindow::setCenterContent(QWidget * const widget, int stretch, Qt::Alignment align, int spacerHeight) { if (!widget || m_centerWidget == widget) { return; @@ -67,12 +75,15 @@ void SessionBaseWindow::setCenterContent(QWidget * const widget, Qt::AlignmentFl m_centerLayout->removeWidget(m_centerWidget); m_centerWidget->hide(); } - m_centerLayout->addWidget(widget, 0, align); + m_centerLayout->addWidget(widget, stretch, align); m_centerSpacerItem->changeSize(0, spacerHeight); + m_centerVLayout->invalidate(); m_centerWidget = widget; widget->show(); + qCInfo(DDE_SHELL) << "centerWidgetHeight: " << widget->height() << "centerWidgetTopSpacerHeight: " << spacerHeight; + setFocusProxy(widget); setFocus(); } @@ -86,6 +97,9 @@ void SessionBaseWindow::setCenterTopWidget(QWidget *const widget) m_centerTopLayout->addWidget(widget, 0, Qt::AlignTop); m_centerTopLayout->addStretch(); m_centerTopWidget = widget; + + const int centerTopHeight = qMax(calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT), m_centerTopWidget->sizeHint().height()); + m_centerTopFrame->setFixedHeight(centerTopHeight); } void SessionBaseWindow::initUI() @@ -93,7 +107,10 @@ void SessionBaseWindow::initUI() //整理代码顺序,让子部件层级清晰明了, //同时方便计算中间区域的大小,使用QFrame替换了QScrollArea m_centerTopLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#else m_centerTopLayout->setMargin(0); +#endif m_centerTopLayout->setSpacing(0); m_centerTopFrame = new QFrame; @@ -103,11 +120,19 @@ void SessionBaseWindow::initUI() m_centerTopFrame->setAutoFillBackground(false); m_centerLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_centerLayout->setContentsMargins(0, 0, 0, 0); +#else m_centerLayout->setMargin(0); +#endif m_centerLayout->setSpacing(0); m_centerVLayout = new QVBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_centerVLayout->setContentsMargins(0, 0, 0, 0); +#else m_centerVLayout->setMargin(0); +#endif m_centerVLayout->setSpacing(0); m_centerVLayout->addSpacerItem(m_centerSpacerItem); m_centerVLayout->addLayout(m_centerLayout); @@ -121,15 +146,26 @@ void SessionBaseWindow::initUI() m_rightBottomLayout = new QHBoxLayout; m_centerBottomLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_leftBottomLayout->setContentsMargins(0, 0, 0, 0); + m_centerBottomLayout->setContentsMargins(0, 0, 0, 0); + m_rightBottomLayout->setContentsMargins(0, 0, 0, 0); +#else m_leftBottomLayout->setMargin(0); - m_leftBottomLayout->setSpacing(0); m_centerBottomLayout->setMargin(0); - m_centerBottomLayout->setSpacing(0); m_rightBottomLayout->setMargin(0); +#endif + + m_leftBottomLayout->setSpacing(0); + m_centerBottomLayout->setSpacing(0); m_rightBottomLayout->setSpacing(0); QHBoxLayout *bottomLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bottomLayout->setContentsMargins(0, 0, 0, 0); +#else bottomLayout->setMargin(0); +#endif bottomLayout->setSpacing(0); bottomLayout->addLayout(m_leftBottomLayout, 3); bottomLayout->addLayout(m_centerBottomLayout, 2); @@ -149,7 +185,30 @@ void SessionBaseWindow::initUI() m_mainLayout->addWidget(m_centerFrame); m_mainLayout->addWidget(m_bottomFrame); - setLayout(m_mainLayout); + QWidget *basewindow = new QWidget(this); + basewindow->setLayout(m_mainLayout); + + m_stackedLayout = new QStackedLayout; + m_stackedLayout->setStackingMode(QStackedLayout::StackOne); + m_stackedLayout->insertWidget(kDefaultWidgetIndex, basewindow); + + setLayout(m_stackedLayout); +} + +void SessionBaseWindow::hideStackedWidgets() +{ + // disable and hide all widgets in stackedLayout + int widCount = m_stackedLayout->count(); + if (widCount) { + for (int index = 0; index < widCount; index++) { + QWidget *tmp = m_stackedLayout->widget(index); + // widgets are not members, so maybe it would be delete somewhere + if (tmp) { + tmp->hide(); + tmp->setDisabled(true); + } + } + } } QSize SessionBaseWindow::getCenterContentSize() @@ -168,11 +227,77 @@ QSize SessionBaseWindow::getCenterContentSize() return QSize(w, h); } +void SessionBaseWindow::setFullManagedLoginWidget(QWidget *wid) +{ + // set wid to nullptr, and the plugin ui would not be show + m_pluginWidgets.insert(PluginWidgetIndex::FullManagedPlugin, wid); + // 如果存在全托管,设为当前界面 + m_stackedLayout->setCurrentIndex(m_stackedLayout->addWidget(wid)); +} + +// for some widgets used by both plugin and default UI +void SessionBaseWindow::showControlFrame(QWidget *wid) +{ + if (!wid) { + return; + } + + hideStackedWidgets(); + + // no need to record index + // just insert the widget if it's isolated + int widIndex = m_stackedLayout->indexOf(wid); + if (widIndex < 0) { + m_stackedLayout->addWidget(wid); + connect(wid, &QWidget::destroyed, this, [&] { + m_stackedLayout->removeWidget(wid); + }); + } + + m_stackedLayout->setCurrentIndex(m_stackedLayout->indexOf(wid)); + wid->show(); + wid->setDisabled(false); +} + +void SessionBaseWindow::showPasswdFrame() +{ + // plugin passwd frame first + auto it = m_pluginWidgets.find(PluginWidgetIndex::FullManagedPlugin); + if (it != m_pluginWidgets.end()) { + QWidget *pluginWid = it.value(); + if (pluginWid) { + showControlFrame(pluginWid); + return; + } + } + + showDefaultFrame(); +} + +// userframe will be part or default widget +// just show default page +void SessionBaseWindow::showDefaultFrame() +{ + hideStackedWidgets(); + + QWidget *defaultWid = m_stackedLayout->widget(kDefaultWidgetIndex); + if (defaultWid) { + defaultWid->setDisabled(false); + defaultWid->show(); + m_stackedLayout->setCurrentIndex(kDefaultWidgetIndex); + } +} + void SessionBaseWindow::resizeEvent(QResizeEvent *event) { + if (!m_centerTopWidget || !m_centerTopFrame || !m_mainLayout) + return; + const int margin = calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN); m_mainLayout->setContentsMargins(0, margin, 0, margin); - m_centerTopFrame->setFixedHeight(calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT)); + + const int centerTopHeight = qMax(calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT), m_centerTopWidget->sizeHint().height()); + m_centerTopFrame->setFixedSize(event->size().width(), centerTopHeight); QFrame::resizeEvent(event); } @@ -187,8 +312,17 @@ void SessionBaseWindow::setBottomFrameVisible(bool visible) m_bottomFrame->setVisible(visible); } -int SessionBaseWindow::calcCurrentHeight(const int height) +int SessionBaseWindow::calcCurrentHeight(int height) const { int h = static_cast(((double) height / (double) BASE_SCREEN_HEIGHT) * topLevelWidget()->geometry().height()); return qMin(h, height); } + +int SessionBaseWindow::calcTopSpacing(int authWidgetTopSpacing) const +{ + if (!m_centerTopWidget) + return qMax(0, authWidgetTopSpacing - calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT)); + + const int topWidgetHeight = qMax(calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT), m_centerTopWidget->sizeHint().height()); + return qMax(0, authWidgetTopSpacing - topWidgetHeight); +} diff --git a/src/session-widgets/sessionbasewindow.h b/src/session-widgets/sessionbasewindow.h index e10d3caf..dfeb4ba1 100644 --- a/src/session-widgets/sessionbasewindow.h +++ b/src/session-widgets/sessionbasewindow.h @@ -1,31 +1,49 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef SESSIONBASEWINDOW_H #define SESSIONBASEWINDOW_H #include #include +#include #include #include +#include class SessionBaseWindow : public QFrame { Q_OBJECT public: + // try to index different plugin widgets here + enum PluginWidgetIndex { + FullManagedPlugin, // full managed, plugin should take control both UI and PAM + EULAPlugin, // EULA, you can place some EULA-like things on login UI + }; + explicit SessionBaseWindow(QWidget *parent = nullptr); virtual void setLeftBottomWidget(QWidget *const widget) final; virtual void setCenterBottomWidget(QWidget *const widget) final; virtual void setRightBottomWidget(QWidget *const widget) final; - virtual void setCenterContent(QWidget *const widget, Qt::AlignmentFlag align = Qt::AlignCenter, int spacerHeight = 0) final; + virtual void setCenterContent(QWidget *const widget, int stretch = 0, Qt::Alignment align = Qt::Alignment(), int spacerHeight = 0) final; virtual void setCenterTopWidget(QWidget *const widget) final; QSize getCenterContentSize(); + void setFullManagedLoginWidget(QWidget *); + void showControlFrame(QWidget *); + void showPasswdFrame(); + void showDefaultFrame(); protected: void setTopFrameVisible(bool visible); void setBottomFrameVisible(bool visible); void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; - int calcCurrentHeight(const int height); + int calcCurrentHeight(int height) const; + int calcTopSpacing(int authWidgetTopSpacing) const; private: void initUI(); + void hideStackedWidgets(); protected: QFrame *m_centerTopFrame; @@ -44,6 +62,8 @@ class SessionBaseWindow : public QFrame QWidget *m_centerBottomWidget; QWidget *m_rightBottomWidget; QSpacerItem *m_centerSpacerItem; + QStackedLayout *m_stackedLayout; + QMap m_pluginWidgets; }; #endif // SESSIONBASEWINDOW_H diff --git a/src/session-widgets/sfa_widget.cpp b/src/session-widgets/sfa_widget.cpp index 309522f1..067d1391 100644 --- a/src/session-widgets/sfa_widget.cpp +++ b/src/session-widgets/sfa_widget.cpp @@ -1,42 +1,27 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "sfa_widget.h" #include "auth_custom.h" #include "auth_face.h" +#include "auth_passkey.h" #include "auth_fingerprint.h" #include "auth_iris.h" #include "auth_password.h" #include "auth_single.h" #include "auth_ukey.h" +#include "authcommon.h" #include "dlineeditex.h" -#include "framedatabind.h" #include "keyboardmonitor.h" -#include "modules_loader.h" #include "sessionbasemodel.h" #include "useravatar.h" +#include "plugin_manager.h" +#include "login_plugin_util.h" +#include "signal_bridge.h" #include -#include #include @@ -50,8 +35,9 @@ SFAWidget::SFAWidget(QWidget *parent) , m_biometricAuthState(nullptr) , m_retryButton(new DFloatingButton(this)) , m_bioAuthStatePlaceHolder(new QSpacerItem(0, BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT)) - , m_bioBottomSpacingHolder(new QSpacerItem(0, BIO_AUTH_STATE_BOTTOM_SPACING)) - , m_authTypeBottomSpacingHolder(new QSpacerItem(0, CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING)) + , m_bioBottomSpacingHolder(new QSpacerItem(0, calcCurrentHeight(BIO_AUTH_STATE_BOTTOM_SPACING))) + , m_authTypeBottomSpacingHolder(new QSpacerItem(0, calcCurrentHeight(CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING))) + , m_currentAuthType(AT_All) { setObjectName(QStringLiteral("SFAWidget")); setAccessibleName(QStringLiteral("SFAWidget")); @@ -60,22 +46,23 @@ SFAWidget::SFAWidget(QWidget *parent) setMinimumSize(280, 176); } +SFAWidget::~SFAWidget() +{ + +} + void SFAWidget::initUI() { AuthWidget::initUI(); - /* 用户名输入框 */ - std::function accountChanged = std::bind(&SFAWidget::syncAccount, this, std::placeholders::_1); - m_registerFunctions["SFAAccount"] = m_frameDataBind->registerFunction("SFAAccount", accountChanged); - m_frameDataBind->refreshData("SFAAccount"); /* 认证选择 */ - m_chooseAuthButtonBox = new DButtonBox(this); - m_chooseAuthButtonBox->setOrientation(Qt::Horizontal); + m_chooseAuthButtonBox = new ButtonBox(this); m_chooseAuthButtonBox->setFocusPolicy(Qt::NoFocus); m_chooseAuthButtonBox->setContentsMargins(0, 0, 0, 0); - m_chooseAuthButtonBox->setMaximumHeight(36); + m_chooseAuthButtonBox->setFixedHeight(CHOOSE_AUTH_TYPE_PLACE_HOLDER_HEIGHT); /* 生物认证状态 */ m_biometricAuthState = new DLabel(this); + m_biometricAuthState->setFixedHeight(BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT); m_biometricAuthState->hide(); /* 重试按钮 */ @@ -83,20 +70,22 @@ void SFAWidget::initUI() m_retryButton->hide(); m_mainLayout->setContentsMargins(10, 0, 10, 0); - m_mainLayout->setSpacing(10); + m_mainLayout->setSpacing(0); m_mainLayout->addWidget(m_biometricAuthState, 0, Qt::AlignCenter); m_mainLayout->addItem(m_bioAuthStatePlaceHolder); m_mainLayout->addItem(m_bioBottomSpacingHolder); m_mainLayout->addWidget(m_chooseAuthButtonBox, 0, Qt::AlignCenter); m_mainLayout->addItem(m_authTypeBottomSpacingHolder); - m_mainLayout->addWidget(m_userAvatar); - m_mainLayout->addWidget(m_nameLabel, 0, Qt::AlignVCenter); - m_mainLayout->addWidget(m_accountEdit, 0, Qt::AlignVCenter); - m_mainLayout->addSpacing(10); + SpacerItemBinder::addWidget(m_userAvatar, m_mainLayout, Qt::AlignVCenter, 5); + SpacerItemBinder::addWidget(m_accountEdit, m_mainLayout, Qt::AlignVCenter, 20); + SpacerItemBinder::addWidget(m_userNameWidget, m_mainLayout, Qt::AlignVCenter, 20); + m_mainLayout->addSpacing(20); m_mainLayout->addWidget(m_expiredStateLabel); - m_mainLayout->addItem(m_expiredSpacerItem); - m_mainLayout->addWidget(m_lockButton, 0, Qt::AlignCenter); - m_mainLayout->addWidget(m_retryButton, 0, Qt::AlignCenter); + m_mainLayout->addSpacing(10); + SpacerItemBinder::addWidget(m_lockButton, m_mainLayout, Qt::AlignCenter); + SpacerItemBinder::addWidget(m_retryButton, m_mainLayout, Qt::AlignCenter); + + m_mainLayout->invalidate(); } void SFAWidget::initConnections() @@ -104,10 +93,43 @@ void SFAWidget::initConnections() AuthWidget::initConnections(); connect(m_model, &SessionBaseModel::authTypeChanged, this, &SFAWidget::setAuthType); connect(m_model, &SessionBaseModel::authStateChanged, this, &SFAWidget::setAuthState); + connect(m_model, &SessionBaseModel::lightdmPamStartedChanged, this, &SFAWidget::onLightdmPamStartChanged); + connect(m_model, &SessionBaseModel::accountError, this, &SFAWidget::onAccountError); connect(m_accountEdit, &DLineEditEx::textChanged, this, [this](const QString &value) { - m_frameDataBind->updateValue(QStringLiteral("SFAAccount"), value); m_lockButton->setEnabled(!value.isEmpty()); }); +#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0) + connect(SpacerItemBinder::instance(), &SpacerItemBinder::requestInvalidateLayout, m_mainLayout, &QVBoxLayout::invalidate); +#else + connect(&SpacerItemBinder::ref(), &SpacerItemBinder::requestInvalidateLayout, m_mainLayout, &QVBoxLayout::invalidate); +#endif + connect(PluginManager::instance(), &PluginManager::pluginAboutToBeRemoved, this, [this] (const QString &key) { + qCInfo(DDE_SHELL) << key << " about to be removed, destruct custom auth now"; + auto it = m_customAuths.find(key); + if (it == m_customAuths.end()) { + qCWarning(DDE_SHELL) << "Can not find plugin:" << key; + return; + } + const auto &auth = it.value(); + if (!auth) { + qCWarning(DDE_SHELL) << "Custom auth object is nullptr"; + return; + } + const bool isCurrentAuthCustom = currentAuthCustom() == auth; + m_chooseAuthButtonBox->removeButton(m_authButtons.value(auth->customAuthType())); + removeAuthButton(auth); + m_customAuths.remove(auth->getLoginPlugin()->key()); + auth->detachPlugin(); + auth->deleteLater(); + if (isCurrentAuthCustom) { + qCInfo(DDE_SHELL) << key << " is current custom auth, change to first auth"; + if (m_authButtons.size() >= 1) { + emit m_chooseAuthButtonBox->button(m_authButtons.firstKey())->toggled(true); + } else { + qCritical(DDE_SHELL) << "No other auth left, can not change to first auth"; + } + } + }); } void SFAWidget::setModel(const SessionBaseModel *model) @@ -117,132 +139,145 @@ void SFAWidget::setModel(const SessionBaseModel *model) initUI(); initConnections(); - setAuthType(model->getAuthProperty().AuthType); + // 在登陆设置验证类型的时候需要判断当前是否是"..."账户,需要先设置当前用户,在设置验证类型,两者的顺序切勿颠倒。 setUser(model->currentUser()); + setAuthType(model->getAuthProperty().AuthType); } /** * @brief 设置认证类型 * @param type 认证类型 */ -void SFAWidget::setAuthType(const int type) -{ - qDebug() << "SFAWidget::setAuthType:" << type; - if (type & AT_Password) { - initPasswdAuth(); - } else if (m_passwordAuth) { - delete m_passwordAuth; - m_passwordAuth = nullptr; - m_authButtons.value(AT_Password)->deleteLater(); - m_authButtons.remove(AT_Password); - m_frameDataBind->clearValue("SFPasswordAuthState"); - m_frameDataBind->clearValue("SFPasswordAuthMsg"); - } - if (type & AT_Face) { - initFaceAuth(); - } else if (m_faceAuth) { - delete m_faceAuth; - m_faceAuth = nullptr; - m_authButtons.value(AT_Face)->deleteLater(); - m_authButtons.remove(AT_Face); - m_frameDataBind->clearValue("SFFaceAuthState"); - m_frameDataBind->clearValue("SFFaceAuthMsg"); - } - if (type & AT_Iris) { - initIrisAuth(); - } else if (m_irisAuth) { - delete m_irisAuth; - m_irisAuth = nullptr; - m_authButtons.value(AT_Iris)->deleteLater(); - m_authButtons.remove(AT_Iris); - m_frameDataBind->clearValue("SFIrisAuthState"); - m_frameDataBind->clearValue("SFIrisAuthMsg"); - } - if (type & AT_Fingerprint) { - initFingerprintAuth(); - } else if (m_fingerprintAuth) { - delete m_fingerprintAuth; - m_fingerprintAuth = nullptr; - m_authButtons.value(AT_Fingerprint)->deleteLater(); - m_authButtons.remove(AT_Fingerprint); - m_frameDataBind->clearValue("SFFingerprintAuthState"); - m_frameDataBind->clearValue("SFFingerprintAuthMsg"); - } - if (type & AT_Ukey) { - initUKeyAuth(); - } else if (m_ukeyAuth) { - delete m_ukeyAuth; - m_ukeyAuth = nullptr; - m_authButtons.value(AT_Ukey)->deleteLater(); - m_authButtons.remove(AT_Ukey); - m_frameDataBind->clearValue("SFUKeyAuthState"); - m_frameDataBind->clearValue("SFUKeyAuthMsg"); - } - if (type & AT_PAM) { - initSingleAuth(); - } else if (m_singleAuth) { - delete m_singleAuth; - m_singleAuth = nullptr; - m_authButtons.value(AT_PAM)->deleteLater(); - m_authButtons.remove(AT_PAM); - m_frameDataBind->clearValue("SFSingleAuthState"); - m_frameDataBind->clearValue("SFSingleAuthMsg"); - } - if (dss::module::ModulesLoader::instance().findModulesByType(dss::module::BaseModuleInterface::LoginType).size() > 0) { - initCustomAuth(); - } else if (m_customAuth) { - delete m_customAuth; - m_customAuth = nullptr; - m_authButtons.value(AT_Custom)->deleteLater(); - m_authButtons.remove(AT_Custom); - m_frameDataBind->clearValue("SFCustomAuthStatus"); - m_frameDataBind->clearValue("SFCustomAuthMsg"); - } - - const int count = m_authButtons.values().size(); - if (count > 0) { - m_chooseAuthButtonBox->setButtonList(m_authButtons.values(), true); - QMap::const_iterator iter = m_authButtons.constBegin(); - while (iter != m_authButtons.constEnd()) { - m_chooseAuthButtonBox->setId(iter.value(), iter.key()); - ++iter; - } - if (count > 1) { - m_chooseAuthButtonBox->show(); - if (type & m_user->lastAuthType()) { - if (m_chooseAuthButtonBox->checkedId() == m_user->lastAuthType()) { - emit m_chooseAuthButtonBox->button(m_user->lastAuthType())->toggled(true); - } else { - m_chooseAuthButtonBox->button(m_user->lastAuthType())->setChecked(true); - } - } else { - if (m_chooseAuthButtonBox->checkedId() == m_authButtons.firstKey()) { - emit m_chooseAuthButtonBox->button(m_authButtons.firstKey())->toggled(true); - } else { - m_chooseAuthButtonBox->button(m_authButtons.firstKey())->setChecked(true); +void SFAWidget::setAuthType(const AuthFlags type) +{ + qCInfo(DDE_SHELL) << "Auth type:" << type; + AuthFlags authType = type; + // 如果密码已过期且当前用户不允许修改密码,则将认证类型改为密码认证 + if (!m_model->currentUser()->allowToChangePassword() && m_model->appType() == Login) { + qCInfo(DDE_SHELL) << "Password is expired, current user is not allowed to change the password, set authentication type to `AT_Password`"; + authType = AT_Password; + } + + // 隐藏生物认证结果状态图标 + m_biometricAuthState->hide(); + + // 初始化认证因子 + initAuthFactors(type); + + // 初始化认证选择按钮组 + initChooseAuthButtonBox(type); + + // 选择默认认证的类型 + chooseAuthType(authType); + + // 如果是无密码认证,焦点默认在解锁按钮上面 + if (m_model->currentUser()->isNoPasswordLogin() && !m_model->terminalLocked()) { + m_lockButton->setEnabled(true); + setFocusProxy(m_lockButton); + setFocus(); + } + + // 界面创建完毕后调整页面高度 + updateSpaceItem(); +} + +/** + * @brief 初始化自定义认证因子 + * + * @param type 当前支持的认证因子 + * @return int 如果自定义认证因子可用,那么在入参的type基础上增加自定义认证因子 + */ +void SFAWidget::initCustomFactors(const AuthFlags type) +{ + PluginManager::instance()->broadcastAuthFactors(type); + auto plugins = filtrateAuthPlugins(PluginManager::instance()->getLoginPlugins()); + qCInfo(DDE_SHELL) << "Login plugin size:" << plugins.size(); + if (!m_model->terminalLocked() && !plugins.isEmpty() && (type & AT_Custom)) { + for (const auto plugin : plugins) { + if (plugin) { + plugin->updateConfig(); + // 手势认证当前还未适配单因认证 + if (plugin->defaultAuthType() & AT_Pattern) { + continue; } + + initCustomAuth(plugin); } - } else { - if (m_chooseAuthButtonBox->checkedId() == m_authButtons.firstKey()) { - emit m_chooseAuthButtonBox->button(m_authButtons.firstKey())->toggled(true); - } else { - m_chooseAuthButtonBox->button(m_authButtons.firstKey())->setChecked(true); + } + + // 析构不使用的插件 + for (const auto &auth : m_customAuths.values()) { + if (!plugins.contains(auth->getLoginPlugin())) { + qCInfo(DDE_SHELL) << "Remove custom auth:" << auth->getLoginPlugin()->key(); + removeAuthButton(auth); + m_customAuths.remove(auth->getLoginPlugin()->key()); + auth->deleteLater(); } - m_chooseAuthButtonBox->hide(); } - std::function authTypeChanged = std::bind(&SFAWidget::syncAuthType, this, std::placeholders::_1); - registerSyncFunctions("SFAType", authTypeChanged); + // 增加输入账户名的界面 + if (type == AT_None && m_user->type() == User::Default) { + initAccount(); + } } else { - m_chooseAuthButtonBox->hide(); + qCInfo(DDE_SHELL) << "Remove all custom auths"; + for (const auto& auth : m_customAuths.values()) + removeAuthButton(auth); + qDeleteAll(m_customAuths); + m_customAuths.clear(); + + if (m_customAuth) { + delete m_customAuth; + m_customAuth = nullptr; + } + + // fix152437,避免初始化其他认证方式图像和nameLabel为隐藏 + m_userAvatar->setVisible(true); + m_lockButton->setVisible(true); + if (m_user->type() != User::Default) + m_userNameWidget->setVisible(true); } - if (m_model->currentUser()->isNoPasswordLogin()) { - m_lockButton->setEnabled(true); - setFocusProxy(m_lockButton); - setFocus(); + if (type != AT_None || m_customAuths.isEmpty() || m_user->type() != User::Default) { + auto btn = m_authButtons.value(AT_None); + if (btn) { + btn->deleteLater(); + btn = nullptr; + m_authButtons.remove(AT_None); + } } +} - updateSpaceItem(); +/** + * @brief 初始化认证因子 + * + * @param type 从DA传入的可支持的认证因子 + * @return int 如果自定义认证因子可用,那么在入参的type基础上增加自定义认证因子 + */ +void SFAWidget::initAuthFactors(const AuthFlags authFactors) +{ + initCustomFactors(authFactors); + + auto updateAuthType = [this, authFactors](AuthType type, + AuthModule *authenticator, + void (SFAWidget::*initAuthFunc)()) { + if (authFactors.testFlag(type)) { + // After passing face or iris verification, if there is a timeout before entering the desktop, re-verification is required + (this->*initAuthFunc)(); + } else if (authenticator) { + delete authenticator; + authenticator = nullptr; + m_authButtons.value(type)->deleteLater(); + m_authButtons.remove(type); + } + }; + + updateAuthType(AT_Password, m_passwordAuth, &SFAWidget::initPasswdAuth); + updateAuthType(AT_Face, m_faceAuth, &SFAWidget::initFaceAuth); + updateAuthType(AT_Iris, m_irisAuth, &SFAWidget::initIrisAuth); + updateAuthType(AT_Fingerprint, m_fingerprintAuth, &SFAWidget::initFingerprintAuth); + updateAuthType(AT_Passkey, m_passkeyAuth, &SFAWidget::initPasskeyAuth); + updateAuthType(AT_Ukey, m_ukeyAuth, &SFAWidget::initUKeyAuth); + updateAuthType(AT_PAM, m_singleAuth, &SFAWidget::initSingleAuth); } /** @@ -251,55 +286,66 @@ void SFAWidget::setAuthType(const int type) * @param state 认证状态 * @param message 认证消息 */ -void SFAWidget::setAuthState(const int type, const int state, const QString &message) +void SFAWidget::setAuthState(const AuthType type, const AuthState state, const QString &message) { - qDebug() << "SFAWidget::setAuthState:" << type << state << message; + qCInfo(DDE_SHELL) << "Set auth state, auth type:" << type + << ", state:" << state + << ", message:" << message; switch (type) { case AT_Password: if (m_passwordAuth) { m_passwordAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFPasswordAuthState", state); - m_frameDataBind->updateValue("SFPasswordAuthMsg", message); } break; case AT_Fingerprint: if (m_fingerprintAuth) { m_fingerprintAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFFingerprintAuthState", state); - m_frameDataBind->updateValue("SFFingerprintAuthMsg", message); } break; case AT_Face: if (m_faceAuth) { m_faceAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFFaceAuthState", state); - m_frameDataBind->updateValue("SFFaceAuthMsg", message); } break; case AT_Ukey: if (m_ukeyAuth) { m_ukeyAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFUKeyAuthState", state); - m_frameDataBind->updateValue("SFUKeyAuthMsg", message); } break; case AT_Iris: if (m_irisAuth) { m_irisAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFIrisAuthState", state); - m_frameDataBind->updateValue("SFIrisAuthMsg", message); + } + break; + case AT_Passkey: + if (m_passkeyAuth) { + m_passkeyAuth->setAuthState(state, message); } break; case AT_PAM: if (m_singleAuth) { m_singleAuth->setAuthState(state, message); - m_frameDataBind->updateValue("SFSingleAuthState", state); - m_frameDataBind->updateValue("SFSingleAuthMsg", message); + } else if (m_passwordAuth) { + m_passwordAuth->setAuthState(state, message); + } + + // 这里是为了让自定义登陆知道lightdm已经开启验证了 + qCInfo(DDE_SHELL) << "Current auth type is: " << m_currentAuthType; + if (currentAuthCustom() && state == AS_Prompt) { + // 有可能DA发送了验证开始,但是lightdm的验证还未开始,此时发送token的话lightdm无法验证通过。 + // lightdm的pam发送prompt后则认为lightdm验证已经开始 + qCInfo(DDE_SHELL) << "LightDM is in authentication right now"; + currentAuthCustom()->lightdmAuthStarted(); + } + + if (m_passwordAuth && m_passwordAuth->isPasswdAuthWidgetReplaced()) { + qCDebug(DDE_SHELL) << Q_FUNC_INFO << type << state << message << "startAuth"; + m_passwordAuth->startPluginAuth(); } break; case AT_Custom: - if (m_customAuth) { - m_customAuth->setAuthState(state, message); + if (currentAuthCustom()) { + currentAuthCustom()->setAuthState(state, message); } break; case AT_All: @@ -308,6 +354,11 @@ void SFAWidget::setAuthState(const int type, const int state, const QString &mes default: break; } + + // 同步验证状态给插件 + if (currentAuthCustom()) { + currentAuthCustom()->notifyAuthState(type, state); + } } /** @@ -323,11 +374,9 @@ void SFAWidget::initSingleAuth() m_singleAuth = new AuthSingle(this); m_singleAuth->setCurrentUid(m_model->currentUser()->uid()); replaceWidget(m_singleAuth); - m_frameDataBind->updateValue("SFAType", AT_PAM); + m_singleAuth->setPasswordLineEditEnabled(m_model->currentUser()->allowToChangePassword() || m_model->appType() != Login); - connect(m_singleAuth, &AuthSingle::activeAuth, this, [ this ] { - emit requestStartAuthentication(m_model->currentUser()->name(), AT_PAM); - }); + connect(m_singleAuth, &AuthSingle::activeAuth, this, &SFAWidget::onActiveAuth); connect(m_singleAuth, &AuthSingle::authFinished, this, [this](const int authState) { if (authState == AS_Success) { m_user->setLastAuthType(AT_PAM); @@ -335,46 +384,33 @@ void SFAWidget::initSingleAuth() emit authFinished(); } }); - connect(m_singleAuth, &AuthSingle::requestAuthenticate, this, [ this ] { + connect(m_singleAuth, &AuthSingle::requestAuthenticate, this, [this] { if (m_singleAuth->lineEditText().isEmpty()) { return; } emit sendTokenToAuth(m_model->currentUser()->name(), AT_PAM, m_singleAuth->lineEditText()); }); - connect(m_capslockMonitor, &KeyboardMonitor::capslockStatusChanged, m_singleAuth, &AuthSingle::setCapsLockVisible); + connect(KeyboardMonitor::instance(), &KeyboardMonitor::capsLockStatusChanged, m_singleAuth, &AuthSingle::setCapsLockVisible); connect(m_lockButton, &QPushButton::clicked, m_singleAuth, &AuthSingle::requestAuthenticate); - /* 输入框数据同步(可能是密码或PIN) */ - std::function tokenChanged = std::bind(&SFAWidget::syncSingle, this, std::placeholders::_1); - registerSyncFunctions("SFSingleAuth", tokenChanged); - connect(m_singleAuth, &AuthSingle::lineEditTextChanged, this, [ this ] (const QString &value) { - m_frameDataBind->updateValue("SFSingleAuth", value); - m_lockButton->setEnabled(!value.isEmpty()); - }); - /* 重置密码可见性数据同步 */ - std::function resetPasswordVisibleChanged = std::bind(&SFAWidget::syncSingleResetPasswordVisibleChanged, this, std::placeholders::_1); - registerSyncFunctions("SingleResetPasswordVisible", resetPasswordVisibleChanged); - connect(m_singleAuth, &AuthSingle::resetPasswordMessageVisibleChanged, this, [ this ] (const bool value) { - m_frameDataBind->updateValue("SingleResetPasswordVisible", value); + connect(m_singleAuth, &AuthSingle::lineEditTextChanged, this, [this](const QString &value) { + m_lockButton->setEnabled(!value.isEmpty()); }); m_singleAuth->setKeyboardButtonVisible(m_keyboardList.size() > 1 ? true : false); m_singleAuth->setKeyboardButtonInfo(m_keyboardType); - m_singleAuth->setCapsLockVisible(m_capslockMonitor->isCapslockOn()); + m_singleAuth->setCapsLockVisible(KeyboardMonitor::instance()->isCapsLockOn()); m_singleAuth->setPasswordHint(m_model->currentUser()->passwordHint()); - // m_singleAuth->setAuthState(m_frameDataBind->getValue("SFSingleAuthState").toInt(), - // m_frameDataBind->getValue("SFSingleAuthMsg").toString()); /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(Password_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Password_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_PAM, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_singleAuth); - m_frameDataBind->updateValue("SFAType", AT_PAM); m_biometricAuthState->hide(); setBioAuthStateVisible(nullptr, false); emit requestStartAuthentication(m_user->name(), AT_PAM); @@ -398,56 +434,95 @@ void SFAWidget::initPasswdAuth() m_passwordAuth = new AuthPassword(this); m_passwordAuth->setCurrentUid(m_model->currentUser()->uid()); m_passwordAuth->hide(); - m_passwordAuth->setShowAuthState(false); + m_passwordAuth->setPasswordLineEditEnabled(m_model->currentUser()->allowToChangePassword() || m_model->appType() != Login); + + connect(m_passwordAuth, &AuthPassword::requestPluginConfigChanged, this, [ this ](const LoginPlugin::PluginConfig pluginConfig) { + m_userAvatar->setVisible(pluginConfig.showAvatar); + m_userNameWidget->setVisible(pluginConfig.showUserName); + m_lockButton->setVisible(pluginConfig.showLockButton); + replaceWidget(m_passwordAuth); + }); - connect(m_passwordAuth, &AuthPassword::activeAuth, this, [this] { - emit requestStartAuthentication(m_user->name(), AT_Password); + connect(m_passwordAuth, &AuthPassword::requestHidePlugin, this, [ this ] { + m_userAvatar->setVisible(true); + m_userNameWidget->setVisible(true); + m_lockButton->setVisible(true); + replaceWidget(m_passwordAuth); + m_passwordAuth->updateResetPasswordUI(); }); - connect(m_passwordAuth, &AuthPassword::authFinished, this, [this](const int authState) { + + connect(m_passwordAuth, &AuthPassword::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_passwordAuth, &AuthPassword::authFinished, this, [this] (const AuthState authState) { checkAuthResult(AT_Password, authState); }); + connect(m_passwordAuth, &AuthPassword::requestPluginAuthToken, this, [this](const QString & account, const QString & token) { + m_passwordAuth->setAuthStateStyle(LOGIN_SPINNER); + m_passwordAuth->setAnimationState(true); + m_passwordAuth->setLineEditEnabled(false); + m_lockButton->setEnabled(false); + qCInfo(DDE_SHELL) << "Request check account: " << account << token; + if (m_user && m_user->name() == account) { + emit sendTokenToAuth(account, AT_Password, token); + return; + } + + Q_EMIT requestCheckAccount(account); + }); connect(m_passwordAuth, &AuthPassword::requestAuthenticate, this, [this] { - const QString &text = m_passwordAuth->lineEditText(); + QString text = m_passwordAuth->lineEditText(); if (text.isEmpty()) { return; } + if (m_passwordAuth->assistLoginWidget()) { + if (m_user) { + Q_EMIT SignalBridge::ref().requestSendExtraInfo(m_user->name(), AT_Password, m_passwordAuth->assistLoginWidget()->extraInfo()); + } else { + qCWarning(DDE_SHELL) << "Current user is null, can not send extra info"; + } + } m_passwordAuth->setAuthStateStyle(LOGIN_SPINNER); m_passwordAuth->setAnimationState(true); m_passwordAuth->setLineEditEnabled(false); m_lockButton->setEnabled(false); + // OPTIMIZING: DA没有发AS_Verify,这里自己发一个,后续DA优化 + m_passwordAuth->setAuthState(AuthCommon::AS_Verify, QStringLiteral("Verifying...")); + + if (m_model->currentUser()->isLdapUser() + && LPUtil::updateLoginType() == LPUtil::Type::CLT_MFA) + { + QJsonObject obj; + obj["password"] = text; + obj["mfa"] = true; + text = QJsonDocument(obj).toJson(QJsonDocument::Compact); + } + emit sendTokenToAuth(m_user->name(), AT_Password, text); }); + + connect(m_passwordAuth, &AuthPassword::notifyLockedStateChanged, this, [this](bool isLocked) { + m_chooseAuthButtonBox->setEnabled(!isLocked); + if (isLocked) { + onRequestChangeAuth(AT_Password); + } + }); + + connect(m_passwordAuth, &AuthPassword::requestUpdateBlurEffectGeometry, this, &SFAWidget::updateBlurEffectGeometry); connect(m_lockButton, &QPushButton::clicked, m_passwordAuth, &AuthPassword::requestAuthenticate); - connect(m_capslockMonitor, &KeyboardMonitor::capslockStatusChanged, m_passwordAuth, &AuthPassword::setCapsLockVisible); - /* 输入框数据同步 */ - std::function passwordChanged = std::bind(&SFAWidget::syncPassword, this, std::placeholders::_1); - registerSyncFunctions("SFPasswordAuth", passwordChanged); + connect(KeyboardMonitor::instance(), &KeyboardMonitor::capsLockStatusChanged, m_passwordAuth, &AuthPassword::setCapsLockVisible); connect(m_passwordAuth, &AuthPassword::lineEditTextChanged, this, [this](const QString &value) { - m_frameDataBind->updateValue("SFPasswordAuth", value); m_lockButton->setEnabled(!value.isEmpty()); }); - /* 重置密码可见性数据同步 */ - std::function resetPasswordVisibleChanged = std::bind(&SFAWidget::syncPasswordResetPasswordVisibleChanged, this, std::placeholders::_1); - registerSyncFunctions("ResetPasswordVisible", resetPasswordVisibleChanged); - connect(m_passwordAuth, &AuthPassword::resetPasswordMessageVisibleChanged, this, [ = ](const bool value) { - m_frameDataBind->updateValue("ResetPasswordVisible", value); - }); - - m_passwordAuth->setCapsLockVisible(m_capslockMonitor->isCapslockOn()); + m_passwordAuth->setCapsLockVisible(KeyboardMonitor::instance()->isCapsLockOn()); m_passwordAuth->setPasswordHint(m_user->passwordHint()); - // m_passwordAuth->setAuthState(m_frameDataBind->getValue("SFPasswordAuthState").toInt(), - // m_frameDataBind->getValue("SFPasswordAuthMsg").toString()); - /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(Password_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Password_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_Password, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_passwordAuth); - m_frameDataBind->updateValue("SFAType", AT_Password); m_biometricAuthState->hide(); setBioAuthStateVisible(nullptr, false); emit requestStartAuthentication(m_user->name(), AT_Password); @@ -459,6 +534,14 @@ void SFAWidget::initPasswdAuth() m_passwordAuth->closeResetPasswordMessage(); } }); + + if (m_passwordAuth->isPasswdAuthWidgetReplaced()) { + if (m_model->appType() == AppType::Lock) { + m_passwordAuth->hidePlugin(); + return; + } + m_passwordAuth->updatePluginConfig(); + } } /** @@ -475,27 +558,21 @@ void SFAWidget::initFingerprintAuth() m_fingerprintAuth->setAuthFactorType(DDESESSIONCC::SingleAuthFactor); m_fingerprintAuth->setAuthStateLabel(m_biometricAuthState); - connect(m_fingerprintAuth, &AuthFingerprint::activeAuth, this, [this] { - emit requestStartAuthentication(m_model->currentUser()->name(), AT_Fingerprint); - }); - connect(m_fingerprintAuth, &AuthFingerprint::authFinished, this, [this](const int authState) { + connect(m_fingerprintAuth, &AuthFingerprint::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_fingerprintAuth, &AuthFingerprint::authFinished, this, [this](const AuthState authState) { checkAuthResult(AT_Fingerprint, authState); }); - // m_fingerprintAuth->setAuthState(m_frameDataBind->getValue("SFPasswordAuthState").toInt(), - // m_frameDataBind->getValue("SFPasswordAuthMsg").toString()); - /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(Fingerprint_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Fingerprint_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_Fingerprint, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_fingerprintAuth); setBioAuthStateVisible(m_fingerprintAuth, true); - m_frameDataBind->updateValue("SFAType", AT_Fingerprint); emit requestStartAuthentication(m_user->name(), AT_Fingerprint); } else { m_fingerprintAuth->hide(); @@ -505,6 +582,54 @@ void SFAWidget::initFingerprintAuth() }); } +/** + * @brief 初始化 Passkey 认证 + */ +void SFAWidget::initPasskeyAuth() +{ + if (m_passkeyAuth) { + m_passkeyAuth->reset(); + return; + } + + m_passkeyAuth = new AuthPasskey(this); + m_passkeyAuth->hide(); + m_passkeyAuth->setAuthFactorType(DDESESSIONCC::SingleAuthFactor); + m_passkeyAuth->setAuthStateLabel(m_biometricAuthState); + + connect(m_passkeyAuth, &AuthPasskey::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_passkeyAuth, &AuthPasskey::authFinished, this, [this](const AuthState authState) { + checkAuthResult(AT_Passkey, authState); + }); + connect(m_passkeyAuth, &AuthPasskey::retryButtonVisibleChanged, this, &SFAWidget::onRetryButtonVisibleChanged); + connect(m_retryButton, &DFloatingButton::clicked, this, [this] { + if (m_currentAuthType != AT_Passkey) { + return; + } + emit requestEndAuthentication(m_model->currentUser()->name(), AT_Passkey); + onRetryButtonVisibleChanged(false); + emit requestStartAuthentication(m_model->currentUser()->name(), AT_Passkey); + }); + + /* 认证选择按钮 */ + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Face_Passkey), QString(), this); + btn->setIconSize(AuthButtonIconSize); + btn->setFixedSize(AuthButtonSize); + btn->setFocusPolicy(Qt::NoFocus); + m_authButtons.insert(AT_Passkey, btn); + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { + if (checked) { + replaceWidget(m_passkeyAuth); + setBioAuthStateVisible(m_passkeyAuth, true); + emit requestStartAuthentication(m_user->name(), AT_Passkey); + } else { + m_passkeyAuth->hide(); + m_lockButton->setEnabled(false); + emit requestEndAuthentication(m_user->name(), AT_Passkey); + } + }); +} + /** * @brief 初始化 UKey 认证 */ @@ -517,13 +642,11 @@ void SFAWidget::initUKeyAuth() m_ukeyAuth = new AuthUKey(this); m_ukeyAuth->hide(); - connect(m_ukeyAuth, &AuthUKey::activeAuth, this, [this] { - emit requestStartAuthentication(m_model->currentUser()->name(), AT_Ukey); - }); - connect(m_ukeyAuth, &AuthUKey::authFinished, this, [this](const int authState) { + connect(m_ukeyAuth, &AuthUKey::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_ukeyAuth, &AuthUKey::authFinished, this, [this](const AuthState authState) { checkAuthResult(AT_Ukey, authState); }); - connect(m_ukeyAuth, &AuthUKey::requestAuthenticate, this, [=] { + connect(m_ukeyAuth, &AuthUKey::requestAuthenticate, this, [this] { const QString &text = m_ukeyAuth->lineEditText(); if (text.isEmpty()) { return; @@ -535,29 +658,24 @@ void SFAWidget::initUKeyAuth() emit sendTokenToAuth(m_model->currentUser()->name(), AT_Ukey, text); }); connect(m_lockButton, &QPushButton::clicked, m_ukeyAuth, &AuthUKey::requestAuthenticate); - connect(m_capslockMonitor, &KeyboardMonitor::capslockStatusChanged, m_ukeyAuth, &AuthUKey::setCapsLockVisible); - /* 输入框数据同步 */ - std::function PINChanged = std::bind(&SFAWidget::syncUKey, this, std::placeholders::_1); - registerSyncFunctions("SFUKeyAuth", PINChanged); + connect(KeyboardMonitor::instance(), &KeyboardMonitor::capsLockStatusChanged, m_ukeyAuth, &AuthUKey::setCapsLockVisible); connect(m_ukeyAuth, &AuthUKey::lineEditTextChanged, this, [this](const QString &value) { - m_frameDataBind->updateValue("SFUKeyAuth", value); if (m_model->getAuthProperty().PINLen > 0 && value.size() >= m_model->getAuthProperty().PINLen) { emit m_ukeyAuth->requestAuthenticate(); } }); - m_ukeyAuth->setCapsLockVisible(m_capslockMonitor->isCapslockOn()); + m_ukeyAuth->setCapsLockVisible(KeyboardMonitor::instance()->isCapsLockOn()); /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(UKey_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(UKey_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_Ukey, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_ukeyAuth); - m_frameDataBind->updateValue("SFAType", AT_Ukey); m_biometricAuthState->hide(); setBioAuthStateVisible(nullptr, false); emit requestStartAuthentication(m_user->name(), AT_Ukey); @@ -585,37 +703,41 @@ void SFAWidget::initFaceAuth() connect(m_faceAuth, &AuthFace::retryButtonVisibleChanged, this, &SFAWidget::onRetryButtonVisibleChanged); connect(m_retryButton, &DFloatingButton::clicked, this, [this] { + if (m_currentAuthType != AT_Face) { + return; + } onRetryButtonVisibleChanged(false); emit requestStartAuthentication(m_model->currentUser()->name(), AT_Face); }); - connect(m_faceAuth, &AuthFace::activeAuth, this, [this] { - emit requestStartAuthentication(m_model->currentUser()->name(), AT_Face); - }); - connect(m_faceAuth, &AuthFace::authFinished, this, [this](const int authState) { + connect(m_faceAuth, &AuthFace::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_faceAuth, &AuthFace::authFinished, this, [this](const AuthState authState) { checkAuthResult(AT_Face, authState); }); connect(m_lockButton, &QPushButton::clicked, this, [this] { if (m_faceAuth == nullptr) return; if (m_faceAuth->authState() == AS_Success) { m_faceAuth->setAuthState(AS_Ended, "Ended"); - emit authFinished(); + + if (m_model->currentUser()->isLdapUser() + && LPUtil::loginType() == LPUtil::Type::CLT_MFA) + { + initCustomMFAAuth(); + } else { + emit authFinished(); + } } }); - // m_faceAuth->setAuthState(m_frameDataBind->getValue("SFFaceAuthState").toInt(), - // m_frameDataBind->getValue("SFFaceAuthMsg").toString()); - /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(Face_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Face_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_Face, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_faceAuth); setBioAuthStateVisible(m_faceAuth, true); - m_frameDataBind->updateValue("SFAType", AT_Face); if (m_faceAuth->authState() != AS_Success) { emit requestStartAuthentication(m_user->name(), AT_Face); } else { @@ -646,35 +768,42 @@ void SFAWidget::initIrisAuth() m_irisAuth->setAuthFactorType(DDESESSIONCC::SingleAuthFactor); connect(m_irisAuth, &AuthIris::retryButtonVisibleChanged, this, &SFAWidget::onRetryButtonVisibleChanged); - connect(m_retryButton, &DFloatingButton::clicked, this, [ this ] { + connect(m_retryButton, &DFloatingButton::clicked, this, [this] { + if (m_currentAuthType != AT_Iris) { + return; + } onRetryButtonVisibleChanged(false); emit requestStartAuthentication(m_model->currentUser()->name(), AT_Iris); }); - connect(m_irisAuth, &AuthIris::activeAuth, this, [ this ] { - emit requestStartAuthentication(m_model->currentUser()->name(), AT_Iris); - }); - connect(m_irisAuth, &AuthIris::authFinished, this, [this](const int authState) { + connect(m_irisAuth, &AuthIris::activeAuth, this, &SFAWidget::onActiveAuth); + connect(m_irisAuth, &AuthIris::authFinished, this, [this](const AuthState authState) { checkAuthResult(AT_Iris, authState); }); connect(m_lockButton, &QPushButton::clicked, this, [this] { if (m_irisAuth == nullptr) return; if (m_irisAuth->authState() == AS_Success) { m_irisAuth->setAuthState(AS_Ended, "Ended"); - emit authFinished(); + + if (m_model->currentUser()->isLdapUser() + && LPUtil::loginType() == LPUtil::Type::CLT_MFA) { + initCustomMFAAuth(); + } else { + emit authFinished(); + } + } }); /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(QIcon(Iris_Auth), QString(), this); + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Iris_Auth), QString(), this); btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); m_authButtons.insert(AT_Iris, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { if (checked) { replaceWidget(m_irisAuth); setBioAuthStateVisible(m_irisAuth, true); - m_frameDataBind->updateValue("SFAType", AT_Iris); if (m_irisAuth->authState() != AS_Success) { emit requestStartAuthentication(m_user->name(), AT_Iris); } else { @@ -690,55 +819,186 @@ void SFAWidget::initIrisAuth() }); } -/** - * @brief 初始化自定义认证 - */ -void SFAWidget::initCustomAuth() +void SFAWidget::initCustomMFAAuth() { + qCDebug(DDE_SHELL) << "Init custom auth"; + + m_chooseAuthButtonBox->hide(); + if (m_passwordAuth) { + m_passwordAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Password); + } + if (m_fingerprintAuth) { + m_fingerprintAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Fingerprint); + } + if (m_faceAuth) { + m_faceAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Face); + } + if (m_passkeyAuth) { + m_passkeyAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Passkey); + } + if (m_irisAuth) { + m_irisAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Iris); + } + if (m_ukeyAuth) { + m_ukeyAuth->hide(); + emit requestEndAuthentication(m_user->name(), AT_Ukey); + } + if (!m_customAuths.isEmpty()) { + for (const auto &auth : m_customAuths) + auth->hide(); + } + if (m_customAuth) { + m_customAuth->reset(); return; } m_customAuth = new AuthCustom(this); - dss::module::LoginModuleInterface *module = dynamic_cast(dss::module::ModulesLoader::instance().findModulesByType(0).values().first()); - module->init(); - m_customAuth->setModule(module); + LoginPlugin *plugin = LPUtil::getLevel2LoginPlugin(); + m_customAuth->setModule(plugin); + m_customAuth->setModel(m_model); + m_customAuth->initUi(); m_customAuth->hide(); - connect(m_customAuth, &AuthCustom::requestAuthenticate, this, [this] { + connect(m_customAuth, &AuthCustom::requestSendToken, this, [this] (const QString &token) { m_lockButton->setEnabled(false); - emit sendTokenToAuth(m_user->name(), AT_Custom, ""); + qCInfo(DDE_SHELL) << "SFA custom send token name :" << m_user->name() << ", token:" << token; + Q_EMIT sendTokenToAuth(m_user->name(), AT_Custom, token); }); connect(m_customAuth, &AuthCustom::authFinished, this, [ this ] (const int authStatus) { if (authStatus == AS_Success) { m_lockButton->setEnabled(true); } }); + connect(m_customAuth, &AuthCustom::requestCheckAccount, this, [this] (const QString &account, bool switchUser) { + qCInfo(DDE_SHELL) << "Request check account: " << account; + if (m_user && m_user->name() == account) { + LoginPlugin::AuthCallbackData data = m_customAuth->getCurrentAuthData(); + if (data.result == LoginPlugin::AuthResult::Success) + Q_EMIT sendTokenToAuth(m_user->name(), AT_Custom, data.token); + else + qCWarning(DDE_SHELL) << Q_FUNC_INFO << "auth failed"; + return; + } + + Q_EMIT requestCheckAccount(account, switchUser); + }); + + connect(m_customAuth, &AuthCustom::notifyAuthTypeChange, this, &SFAWidget::onRequestChangeAuth); + + m_biometricAuthState->hide(); + setBioAuthStateVisible(nullptr, false); + m_accountEdit->hide(); + m_userAvatar->setVisible(m_customAuth->pluginConfig().showAvatar); + m_userNameWidget->setVisible(m_customAuth->pluginConfig().showUserName); + m_lockButton->setVisible(m_customAuth->pluginConfig().showLockButton); + m_blurEffectWidget->setVisible(m_customAuth->pluginConfig().showBackGroundColor); + replaceWidget(m_customAuth); + Q_EMIT requestStartAuthentication(m_user->name(), AT_Custom); +} + +/** + * @brief 初始化自定义认证 + */ +void SFAWidget::initCustomAuth(LoginPlugin* plugin) +{ + qCInfo(DDE_SHELL) << "Init custom auth"; + if (!plugin) { + qCInfo(DDE_SHELL) << "Login plugin is nullptr"; + return; + } + auto it = m_customAuths.find(plugin->key()); + if (it != m_customAuths.end()) { + auto customAuth = *it; + if (customAuth) { + customAuth->reset(); + qCInfo(DDE_SHELL) << "Auth plugin existed:" << customAuth->loginPluginKey(); + return; + } + } + + qCInfo(DDE_SHELL) << "Create new custom authentication with plugin:" << plugin->key(); + auto customAuth = new AuthCustom(this); + customAuth->setModule(plugin); + customAuth->setModel(m_model); + customAuth->initUi(); + customAuth->hide(); + customAuth->setCustomAuthIndex(m_customAuths.count() + 1); + m_blurEffectWidget->setVisible(customAuth->pluginConfig().showBackGroundColor); + m_customAuths.insert(plugin->key(), customAuth); + + connect(customAuth, &AuthCustom::requestSendToken, this, [this, customAuth](const QString &token) { + m_lockButton->setEnabled(false); + qCInfo(DDE_SHELL) << customAuth->loginPluginKey() << " request send token, user name:" << m_user->name(); + Q_EMIT sendTokenToAuth(m_user->name(), customAuth->pluginConfig().assignAuthType, token); + }); + connect(customAuth, &AuthCustom::authFinished, customAuth, [this, customAuth](const AuthState authState) { + qCInfo(DDE_SHELL) << customAuth->loginPluginKey() << " auth finished, state:" << authState; + checkAuthResult(AT_Custom, authState); + if (m_user) + m_user->setLastCustomAuth(customAuth->loginPluginKey()); + }); + connect(customAuth, &AuthCustom::requestCheckAccount, this, [this, customAuth](const QString &account, bool switchUser) { + qCInfo(DDE_SHELL) << customAuth->loginPluginKey() << " request check account:" << account; + if (m_user && m_user->name() == account) { + LoginPlugin::AuthCallbackData data = customAuth->getCurrentAuthData(); + if (data.result == LoginPlugin::AuthResult::Success) + Q_EMIT sendTokenToAuth(m_user->name(), customAuth->pluginConfig().assignAuthType, data.token); + else + qCWarning(DDE_SHELL) << "Custom auth failed"; + + return; + } + + Q_EMIT requestCheckAccount(account, switchUser); + }); + + connect(customAuth, &AuthCustom::notifyAuthTypeChange, this, &SFAWidget::onRequestChangeAuth); /* 认证选择按钮 */ - DButtonBoxButton *btn = new DButtonBoxButton(DStyle::SP_SelectElement, QString(), this); - const QIcon icon(QString::fromStdString(module->icon())); - if (!icon.isNull()) { + ButtonBoxButton *btn = new ButtonBoxButton(DStyle::SP_SelectElement, QString(), this); + btn->setObjectName(plugin->key()); + const QString &iconStr = plugin->icon(); + const QIcon icon = QFile::exists(iconStr) ? QIcon(iconStr) : QIcon::fromTheme(iconStr); + if (!icon.isNull()) btn->setIcon(icon); - } btn->setIconSize(AuthButtonIconSize); btn->setFixedSize(AuthButtonSize); btn->setFocusPolicy(Qt::NoFocus); - m_authButtons.insert(AT_Custom, btn); - connect(btn, &DButtonBoxButton::toggled, this, [this](const bool checked) { + const bool showBtn = plugin->pluginConfig().showSwitchButton; + btn->setVisible(showBtn); + btn->setVisibleAttr(showBtn); + m_authButtons.insert(customAuth->customAuthType(), btn); + connect(btn, &ButtonBoxButton::toggled, this, [this, customAuth](const bool checked) { if (checked) { - replaceWidget(m_customAuth); - m_frameDataBind->updateValue("SFAType", AT_Custom); + qCInfo(DDE_SHELL) << customAuth->loginPluginKey() << " is checked"; m_biometricAuthState->hide(); setBioAuthStateVisible(nullptr, false); - emit requestStartAuthentication(m_user->name(), AT_Custom); - m_nameLabel->hide(); + m_accountEdit->hide(); + m_userAvatar->setVisible(customAuth->pluginConfig().showAvatar); + m_userNameWidget->setVisible(customAuth->pluginConfig().showUserName); + m_lockButton->setVisible(customAuth->pluginConfig().showLockButton); + replaceWidget(customAuth); + Q_EMIT requestStartAuthentication(m_user->name(), customAuth->pluginConfig().assignAuthType); } else { - m_customAuth->hide(); - m_nameLabel->show(); + qCInfo(DDE_SHELL) << customAuth->loginPluginKey() << " is unchecked"; + customAuth->hide(); + m_userNameWidget->show(); + m_userAvatar->show(); + m_lockButton->show(); m_lockButton->setEnabled(false); - emit requestEndAuthentication(m_user->name(), AT_Custom); + if (m_user->type() == User::Default) { + m_userNameWidget->hide(); + m_accountEdit->show(); + m_accountEdit->setFocus(); + } + Q_EMIT requestEndAuthentication(m_user->name(), customAuth->pluginConfig().assignAuthType); } }); } @@ -749,62 +1009,90 @@ void SFAWidget::initCustomAuth() * @param type 认证类型 * @param state 认证状态 */ -void SFAWidget::checkAuthResult(const int type, const int state) +void SFAWidget::checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state) { // 等所有类型验证通过的时候在发送验证完成信息,否则DA的验证结果可能还没有刷新,导致lightdm调用pam验证失败 // 人脸和虹膜是手动点击解锁按钮后发送,无需处理 if (type == AT_All && state == AS_Success) { - if ((m_passwordAuth && AS_Success == m_passwordAuth->authState()) - || (m_ukeyAuth && AS_Success == m_ukeyAuth->authState()) - || (m_fingerprintAuth && AS_Success == m_fingerprintAuth->authState()) - || (m_customAuth && m_customAuth->authState() == AS_Success)) { - if (m_faceAuth) m_faceAuth->setAuthState(AS_Ended, "Ended"); - if (m_irisAuth) m_irisAuth->setAuthState(AS_Ended, "Ended"); - emit authFinished(); + if( m_model->appType() != AppType::Login || m_model->isLightdmPamStarted()){ + sendAuthFinished(); + } + + if (currentAuthCustom()) { + currentAuthCustom()->resetAuth(); } } else if (type != AT_All && state == AS_Success) { - m_user->setLastAuthType(type); + if (type == AuthCommon::AT_Custom ) { + const auto customAuth = currentAuthCustom(); + if (customAuth && customAuth->pluginConfig().saveLastAuthType) + m_user->setLastAuthType(type); + } else { + m_user->setLastAuthType(type); + } m_lockButton->setEnabled(true); m_lockButton->setFocus(); - } -} -/** - * @brief 多屏同步认证类型 - * @param value - */ -void SFAWidget::syncAuthType(const QVariant &value) -{ - QAbstractButton *btn = m_chooseAuthButtonBox->button(value.toInt()); - if (btn) - btn->setChecked(true); + if (type == AT_Face || type == AT_Iris) { + // 禁止切换其他认证方式 + m_chooseAuthButtonBox->setEnabled(false); + } + } } void SFAWidget::replaceWidget(AuthModule *authModule) { - m_mainLayout->insertWidget(layout()->indexOf(m_userAvatar) + 3, authModule); + m_currentAuthType = authModule->authType(); + if (authModule->authType() == AuthCommon::AT_Custom) { + const auto customAuth = qobject_cast(authModule); + if (customAuth) + m_currentAuthType = customAuth->customAuthType(); + } + qCInfo(DDE_SHELL) << "Replace widget, current auth type:" << m_currentAuthType; + m_mainLayout->insertWidget(layout()->indexOf(m_userNameWidget) + 2, authModule); authModule->show(); setFocus(); if (authModule->isLocked()) authModule->clearFocus(); else authModule->setFocus(); - m_lockButton->setEnabled(false); onRetryButtonVisibleChanged(false); + updateBlurEffectGeometry(); + if (m_currentAuthType == AT_PAM) { + if (m_singleAuth && m_singleAuth->lineEditText() == "") { + m_lockButton->setEnabled(false); + } + } else if (m_currentAuthType == AT_Ukey) { + if (m_ukeyAuth && m_ukeyAuth->lineEditText() == "") { + m_lockButton->setEnabled(false); + } + } else if (m_currentAuthType == AT_Password) { + if (m_passwordAuth && m_passwordAuth->lineEditText() == "") { + m_lockButton->setEnabled(false); + } + } else { + m_lockButton->setEnabled(false); + } + + setFocusProxy(authModule); + // 加入事件循环中处理,否则其它控件的geometry还未设置完成,导致UI显示异常 + QTimer::singleShot(0, this, &SFAWidget::updateBlurEffectGeometry); } void SFAWidget::onRetryButtonVisibleChanged(bool visible) { + m_lockButton->setVisible(!visible && !(currentAuthCustom() && !currentAuthCustom()->pluginConfig().showLockButton)); m_retryButton->setVisible(visible); - m_lockButton->setVisible(!visible); + visible ? m_retryButton->setFocus() : updateFocus(); } void SFAWidget::setBioAuthStateVisible(AuthModule *authModule, bool visible) { - bool hasBioAuth = (m_faceAuth || m_fingerprintAuth || m_irisAuth); + bool hasBioAuth = (m_faceAuth || m_fingerprintAuth || m_irisAuth || m_passkeyAuth); m_bioAuthStatePlaceHolder->changeSize(0, (visible || !hasBioAuth) ? 0 : BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT); if (authModule) authModule->setAuthStatueVisible(visible); + + m_mainLayout->invalidate(); } /** @@ -812,30 +1100,63 @@ void SFAWidget::setBioAuthStateVisible(AuthModule *authModule, bool visible) */ int SFAWidget::getTopSpacing() const { - int calcTopHeight = static_cast(topLevelWidget()->geometry().height() * AUTH_WIDGET_TOP_SPACING_PERCENT); - + const qreal pixelRatio = qApp->devicePixelRatio(); + const int topLevelWidgetHeight = topLevelWidget()->geometry().height() * pixelRatio; + const int calcTopHeight = static_cast(topLevelWidgetHeight * AUTH_WIDGET_TOP_SPACING_PERCENT); + const bool showAuthButton = showAuthButtonBox(); + const bool hasBioAuth = (m_faceAuth || m_fingerprintAuth || m_irisAuth || m_passkeyAuth); // 在低分辨率(高度<916)的时候,如果用户头像到屏幕顶端的距离为整个高度的35%,那么验证窗口整体是偏下的。 // 计算居中时的顶部高度,用来保证验证窗口最起码是居中(在分辨率非常低的时候也无法保证,根据测试768是没问题的)。 - int centerTop = static_cast((topLevelWidget()->geometry().height() - MIN_AUTH_WIDGET_HEIGHT) / 2); - const int topHeight = qMin(calcTopHeight, centerTop); + int centerTop = static_cast((topLevelWidgetHeight - MIN_AUTH_WIDGET_HEIGHT) / 2); + if (!m_customAuths.isEmpty()) { + // 一般自定义的类型控件尺寸都会比较大,尽量保证能够居中显示。 + // 根据头像、用户名、锁屏以及插件自身的高度来计算居中时顶部间隔 + // 这是一个相对比较严格的高度,如果插件还是无法显示完整,或者界面偏下的话,只能插件调整content界面的大小了 + bool showAvatar = false; + bool showUserName = false; + bool showLockButton = false; + int maxContentHeight = 0; + for (const auto &auth : m_customAuths) { + const auto &pluginConfig = auth->pluginConfig(); + showAvatar = showAvatar || pluginConfig.showAvatar; + showUserName = showUserName || pluginConfig.showUserName; + showLockButton = showLockButton || pluginConfig.showLockButton; + maxContentHeight = qMax(maxContentHeight, static_cast(auth->contentSizeHint().height() * pixelRatio)); + } - // 需要额外增加的顶部间隔高度 = 屏幕高度*0.35 - 时间控件高度 - 布局间隔 - 生物认证按钮底部间隔 + int height = showAvatar ? m_userAvatar->height() + 10 : 0; + height += showUserName ? m_userNameWidget->height() + 10 : 0; + height += showLockButton ? m_lockButton->height() + 10 : 0; + centerTop = static_cast((topLevelWidgetHeight - height * pixelRatio - maxContentHeight) / 2); +// Just for debug +#if 0 + qCInfo(DDE_SHELL) << "Height:" << height << ", show avatar:" << showAvatar << ", show user name:" << showUserName << ", show lock button:" << showLockButton << ", show auth button:" << showAuthButton; +#endif + } + const int topHeight = qMin(calcTopHeight, centerTop); + // 需要额外增加的顶部间隔高度 = 屏幕高度*0.35 - 布局间隔 - 生物认证按钮底部间隔 // - 生物认证切换按钮底部间隔 - 生物认证图标高度(如果有生物认证因子) - 切换验证类型按钮高度(如果认证因子数量大于1) - int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN) - - calcCurrentHeight(LOCK_CONTENT_TOP_WIDGET_HEIGHT) - - m_bioBottomSpacingHolder->sizeHint().height() - - m_authTypeBottomSpacingHolder->sizeHint().height() - - ((m_faceAuth || m_fingerprintAuth || m_irisAuth) ? BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT : 0) - - (m_authButtons.size() > 1 ? CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING : 0); - + int deltaY = topHeight - calcCurrentHeight(LOCK_CONTENT_CENTER_LAYOUT_MARGIN) * pixelRatio + - (hasBioAuth ? BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT * pixelRatio : 0) + - (hasBioAuth ? calcCurrentHeight(BIO_AUTH_STATE_BOTTOM_SPACING) * pixelRatio : 0) + - (showAuthButton ? calcCurrentHeight(CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING) * pixelRatio : 0) + - (showAuthButton ? CHOOSE_AUTH_TYPE_PLACE_HOLDER_HEIGHT * pixelRatio : 0); + +// Just for debug +#if 0 + qCInfo(DDE_SHELL) << "Top height:" << topHeight << ", center top:" << centerTop << ", deltaY:" << deltaY << ", pixelRatio:" << pixelRatio << ", show auth button:" << showAuthButton << ", hasBioAuth: " << hasBioAuth; +#endif + + deltaY = deltaY / pixelRatio; return qMax(15, deltaY); } void SFAWidget::resizeEvent(QResizeEvent *event) { - AuthWidget::resizeEvent(event); - updateSpaceItem(); + QTimer::singleShot(0, this, &SFAWidget::updateBlurEffectGeometry); + + AuthWidget::resizeEvent(event); } /** @@ -843,17 +1164,22 @@ void SFAWidget::resizeEvent(QResizeEvent *event) */ void SFAWidget::updateSpaceItem() { - m_authTypeBottomSpacingHolder->changeSize(0, m_authButtons.size() > 1 ? calcCurrentHeight(CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING) : 0); + m_authTypeBottomSpacingHolder->changeSize(0, showAuthButtonBox() ? calcCurrentHeight(CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING) : 0); - if (m_faceAuth || m_fingerprintAuth || m_irisAuth) { - m_bioBottomSpacingHolder->changeSize(0, calcCurrentHeight(CHOOSE_AUTH_TYPE_BUTTON_BOTTOM_SPACING)); + if (m_faceAuth || m_fingerprintAuth || m_irisAuth || m_passkeyAuth) { + m_bioBottomSpacingHolder->changeSize(0, calcCurrentHeight(BIO_AUTH_STATE_BOTTOM_SPACING)); m_bioAuthStatePlaceHolder->changeSize(0, m_bioAuthStatePlaceHolder->sizeHint().height() == 0 ? 0 : BIO_AUTH_STATE_PLACE_HOLDER_HEIGHT); } else { m_bioBottomSpacingHolder->changeSize(0, 0); m_bioAuthStatePlaceHolder->changeSize(0, 0); } - - emit updateParentLayout(); + // QSpacerItem 调用了changeSize后需要其所属的layout调用一下invalidate,详见是qt的说明: + // Note that if changeSize() is called after the spacer item has been added to a layout, + // it is necessary to invalidate the layout in order for the spacer item's new size to take effect. + m_mainLayout->invalidate(); + // 不是锁屏界面不重绘,会导致界面下移 + if (isVisible()) + emit updateParentLayout(); } void SFAWidget::updateFocus() @@ -861,8 +1187,14 @@ void SFAWidget::updateFocus() for (int i = 0; i < m_mainLayout->layout()->count(); ++i) { AuthModule *authModule = qobject_cast(m_mainLayout->layout()->itemAt(i)->widget()); if (authModule && authModule->authType() == m_chooseAuthButtonBox->checkedId()) { + if (currentAuthCustom() && !currentAuthCustom()->pluginConfig().showSwitchButton) { + return; + } setFocus(); - if (authModule->isLocked()) + + if (m_authState == AuthCommon::AS_Success && m_lockButton->isEnabled()) + m_lockButton->setFocus(); + else if (authModule->isLocked()) authModule->clearFocus(); else authModule->setFocus(); @@ -876,5 +1208,382 @@ void SFAWidget::showEvent(QShowEvent *event) { AuthWidget::showEvent(event); + updateSpaceItem(); + QTimer::singleShot(0, this, &SFAWidget::updateBlurEffectGeometry); QTimer::singleShot(0, this, &SFAWidget::updateFocus); } + +void SFAWidget::updateBlurEffectGeometry() +{ + const auto currenAuthCustom = currentAuthCustom(); + if (currenAuthCustom) { + QRect rect = this->rect(); + // top + if (!currenAuthCustom->pluginConfig().showAvatar) { + if (currenAuthCustom->pluginConfig().showUserName) { + rect.setTop(m_userNameWidget->geometry().top() - 10); + } else { + rect.setTop(currenAuthCustom->geometry().top() - 10); + } + } else { + rect.setTop(m_userAvatar->geometry().top() + m_userAvatar->height() / 2); + } + // bottom + if (m_user->expiredState() == User::ExpiredNormal) { + if (!currenAuthCustom->pluginConfig().showLockButton) { + rect.setBottom(currenAuthCustom->geometry().bottom() + 10); + } else { + rect.setBottom(m_lockButton->geometry().top() - 20); + } + } else { + rect.setBottom(m_expiredStateLabel->geometry().top() - 10); + } + m_blurEffectWidget->setGeometry(rect); + m_blurEffectWidget->update(); + } else if (m_passwordAuth && m_passwordAuth->isPasswdAuthWidgetReplaced()) { + QRect rect = this->rect(); + rect.setTop(m_userAvatar->geometry().top()); + rect.setBottom(m_lockButton->geometry().top() - 10); + m_blurEffectWidget->setGeometry(rect); + m_blurEffectWidget->update(); + } else { + AuthWidget::updateBlurEffectGeometry(); + } +} + +void SFAWidget::initAccount() +{ + qCDebug(DDE_SHELL) << "Init switch button of account"; + /* 认证选择按钮 */ + if (m_authButtons.contains(AT_None)) { + return; + } + ButtonBoxButton *btn = new ButtonBoxButton(QIcon(Password_Auth), QString(), this); + btn->setIconSize(AuthButtonIconSize); + btn->setFixedSize(AuthButtonSize); + btn->setFocusPolicy(Qt::NoFocus); + m_authButtons.insert(AT_None, btn); + connect(btn, &ButtonBoxButton::toggled, this, [this](const bool checked) { + if (checked) { + m_accountEdit->show(); + m_lockButton->show(); + m_currentAuthType = AT_None; + setBioAuthStateVisible(nullptr, false); + } else { + m_accountEdit->hide(); + } + }); +} + +void SFAWidget::onRequestChangeAuth(AuthType authType) +{ + qCInfo(DDE_SHELL) << "Request change auth, auth type: " << authType + << ", choose auth button box is enabled: " << m_chooseAuthButtonBox->isEnabled() + << ", current authentication type: " << m_currentAuthType; + + int authTypeTmp = authType; + const auto customAuth = qobject_cast(sender()); + if (customAuth && customAuth->customAuthType() != m_currentAuthType) { + // 输出一下日志表明是哪个插件请求切换的,目前遇到的场景:锁屏时开启了密码认证,云桌面需要切换单点登录插件认证,自动解锁。 + qCInfo(DDE_SHELL) << "Custom auth mismatch with current auth type, custom auth type: " << customAuth->customAuthType(); + } + + if (authTypeTmp == m_currentAuthType) { + qCInfo(DDE_SHELL) << "Current auth type is same with request auth type"; + return; + } + + if (authTypeTmp != AuthCommon::AT_Password && !m_chooseAuthButtonBox->isEnabled()) { + qCInfo(DDE_SHELL) << "Authentication button box is disabled and authentication type is not password, automatically switch to password authentication"; + authTypeTmp = AT_Password; + } + + // 如果请求切换到AT_All 表明请求方无所谓切换到某种特定的类型,交由登录器来处理。 + // 登录器会切换到上次认证成功的类型。 + if (authTypeTmp == AuthCommon::AT_All) { + qCInfo(DDE_SHELL) << "Request authentication type is AT_All, let the session-shell to handle it"; + if (m_user) { + authTypeTmp = m_user->lastAuthType(); + } else { + qCWarning(DDE_SHELL) << "No user, use first auth type"; + authTypeTmp = m_authButtons.firstKey(); + } + } + + if (!m_authButtons.contains(authTypeTmp)) { + qCWarning(DDE_SHELL) << "Authentication buttons do not contain the type"; + + // 登录选项默认显示上一次认证方式,当不存在上一次认证,默认显示第一种认证方式 + QAbstractButton *button = nullptr; + const auto lastAuthType = m_user->lastAuthType(); + qCInfo(DDE_SHELL) << "Last authtication type:" << lastAuthType; + if (lastAuthType == AuthCommon::AT_Custom) { + authTypeTmp = m_authButtons.firstKey(); + // 获取上次自定义认证的类型 + const auto &lastCustomAuth = m_user->lastCustomAuth(); + qCInfo(DDE_SHELL) << "Last custom auth:" << lastCustomAuth; + if (!lastCustomAuth.isEmpty() && m_customAuths.contains(lastCustomAuth)) { + const auto &it = m_customAuths.find(lastCustomAuth); + if (it != m_customAuths.end() && it.value() != nullptr) { + // 排除重复使用了当前自定义认证类型的情况 + if (!customAuth || customAuth->customAuthType() != it.value()->customAuthType()) + authTypeTmp = it.value()->customAuthType(); + } + } + button = m_chooseAuthButtonBox->button(authTypeTmp); + } else if (m_authButtons.contains(lastAuthType)) { + button = m_chooseAuthButtonBox->button(lastAuthType); + } else { + button = m_chooseAuthButtonBox->button(m_authButtons.firstKey()); + } + + if (button) { + button->setChecked(true); + } else { + qCWarning(DDE_SHELL) << "Authentication button is nullptr"; + } + + return ; + } + + QAbstractButton *btn = m_chooseAuthButtonBox->button(authTypeTmp); + if (!btn) { + qCWarning(DDE_SHELL) << "The button of authentication is null"; + return; + } + + btn->setChecked(true); +} + +QList SFAWidget::filtrateAuthPlugins(const QList &plugins) const +{ + QList retList; + if (plugins.isEmpty()) { + qCInfo(DDE_SHELL) << "There is no login plugin"; + return retList; + } + + // 无密码登录或者自动登录不使用自定义认证 + // 去掉自动登录的判定,详见bug176463 + if (m_model->currentUser()->isNoPasswordLogin()) { + qCInfo(DDE_SHELL) << "No password login is enabled"; + return retList; + } + + // 主账户登录,切换用户b(在greeter界面),回到主账户后删除b账户,这个时候greeter切换用户到主账户 + const bool isLoginedUserInGreeter = m_model->appType() == Login && m_user->isLogin(); + qCInfo(DDE_SHELL) << "Current user is logged in: " << isLoginedUserInGreeter; + + for (const auto plugin : plugins) { + if (!plugin->isPluginEnabled()) + continue; + if (isLoginedUserInGreeter && plugin->pluginConfig().notUsedByLoginedUserInGreeter) + continue; + retList.append(plugin); + } + + // 判断认证插件是否支持"..."用户 + if (m_user && m_user->type() == User::Default) { + auto tmpList = retList; + retList.clear(); + for (const auto plugin : tmpList) { + if (plugin->supportDefaultUser()) + retList.append(plugin); + } + } + + return retList; +} + +AuthCustom *SFAWidget::currentAuthCustom() const +{ + if (m_customAuth) + return m_customAuth; + + if (m_currentAuthType >= AuthCommon::AT_Custom && !m_customAuths.isEmpty()) { + for (const auto &auth : m_customAuths.values()) { + if (auth && auth->customAuthType() == m_currentAuthType) + return auth; + } + } + + return nullptr; +} + +bool SFAWidget::useCustomAuth() const +{ + return filtrateAuthPlugins(PluginManager::instance()->getLoginPlugins()).isEmpty(); +} + +void SFAWidget::onActiveAuth(AuthType authType) +{ + if (m_currentAuthType != authType) { + qCWarning(DDE_SHELL) << "Active authentication mismatch the current authentication type"; + return; + } + + emit requestStartAuthentication(m_model->currentUser()->name(), authType); +} + +void SFAWidget::onAccountError() +{ + QList> authCustomWidgets = m_customAuths.values(); + for (const QPointer &authCustonWidget : authCustomWidgets) { + LoginPlugin *loginPlugin = authCustonWidget->getLoginPlugin(); + loginPlugin->accountError(); + } +} + +void SFAWidget::initChooseAuthButtonBox(const AuthFlags authFlags) +{ + m_chooseAuthButtonBox->setEnabled(true); + + m_chooseAuthButtonBox->setVisible(m_authButtons.count() > 1); + if (!m_authButtons.isEmpty()) { + m_chooseAuthButtonBox->setButtonList(m_authButtons.values(), true); + auto iter = m_authButtons.constBegin(); + while (iter != m_authButtons.constEnd()) { + m_chooseAuthButtonBox->setId(iter.value(), iter.key()); + ++iter; + } + } + + m_chooseAuthButtonBox->setVisible(showAuthButtonBox()); +} + +void SFAWidget::chooseAuthType(const AuthFlags authFlags) +{ + if (m_authButtons.isEmpty()) + return; + + do + { + // 只有一种认证类型,直接使用 + if (m_authButtons.count() == 1) { + qCInfo(DDE_SHELL) << "Only one authentication type, use first auth type"; + m_currentAuthType = m_authButtons.firstKey(); + break; + } + // 如果密码锁定,那么切换到密码认证且不允许切换认证类型 + if (m_passwordAuth && m_passwordAuth->isLocked()) { + qCInfo(DDE_SHELL) << "Password is locked, use password authentication"; + m_chooseAuthButtonBox->setEnabled(false); + m_user->setLastAuthType(AT_Password); + m_currentAuthType = AT_Password; + break; + } + // 自定义认证插件的认证顺序 + if (!m_customAuths.isEmpty()) { + // order 的优先级最高 + int customAuth = -1; + const auto& authOrder = DConfigHelper::instance()->getConfig(DDESESSIONCC::LOGIN_PLUGIN_AUTH_ORDER, {}).toStringList(); + qCInfo(DDE_SHELL) << "Login plugin auth order:" << authOrder; + for (const auto &authType : authOrder) { + if (m_customAuths.contains(authType)) { + customAuth = m_customAuths.value(authType)->customAuthType(); + break; + } + } + if (customAuth != -1) { + m_currentAuthType = customAuth; + break; + } + // 遍历自定义认证,找到级别最高的 + for (const auto &auth : m_customAuths) { + if (auth->pluginConfig().defaultAuthLevel == LoginPlugin::DefaultAuthLevel::StrongDefault) { + customAuth = auth->customAuthType(); + break; + } + } + if (customAuth != -1) { + m_currentAuthType = customAuth; + break; + } + } + // 使用上一次认证成功类型 + if (authFlags & m_user->lastAuthType()) { + m_currentAuthType = m_user->lastAuthType(); + qCInfo(DDE_SHELL) << "Last auth type:" << m_currentAuthType; + // 上一次认证成功的类型是自定义认证 + if (m_currentAuthType == AT_Custom) { + if (!m_customAuths.isEmpty()) { + m_currentAuthType = (int)AT_Custom + 1; + // 获取上次自定义认证的类型 + const auto lastCustomAuth = m_user->lastCustomAuth(); + qCInfo(DDE_SHELL) << "Last custom auth:" << lastCustomAuth; + if (!lastCustomAuth.isEmpty() && m_customAuths.contains(lastCustomAuth)) { + auto it = m_customAuths.find(lastCustomAuth); + if (it != m_customAuths.end() && it.value() != nullptr) { + m_currentAuthType = it.value()->customAuthType(); + } + } + } else { + qCInfo(DDE_SHELL) << "No custom auth, use first auth type"; + m_currentAuthType = m_authButtons.firstKey(); + } + } + } + // 防呆处理,排除异常情况 + if (!(authFlags & m_currentAuthType) || m_currentAuthType == AT_All || !m_authButtons.contains(m_currentAuthType)) + m_currentAuthType = m_authButtons.firstKey(); + } while(0); + + qCInfo(DDE_SHELL) << "Change auth type:" << m_currentAuthType; + if (m_chooseAuthButtonBox->checkedId() == m_currentAuthType) { + emit m_chooseAuthButtonBox->button(m_currentAuthType)->toggled(true); + } else { + m_chooseAuthButtonBox->button(m_currentAuthType)->setChecked(true); + } +} + +bool SFAWidget::showAuthButtonBox() const +{ + int count = 0; + for (const auto &btn : m_chooseAuthButtonBox->buttonBoxList()) + count += btn->testVisibleAttr() ? 1: 0; + // 那么当认证因子大于1时才显示切换认证按钮组 + return count > 1; +} + +void SFAWidget::onLightdmPamStartChanged() +{ + if (m_model->getAuthResult().authType == AT_All && m_model->getAuthResult().authState == AS_Success) { + sendAuthFinished(); + } +} + +void SFAWidget::sendAuthFinished() +{ + if ((m_passwordAuth && AS_Success == m_passwordAuth->authState()) + || (m_ukeyAuth && AS_Success == m_ukeyAuth->authState()) + || (m_fingerprintAuth && AS_Success == m_fingerprintAuth->authState()) + || (m_passkeyAuth && AS_Success == m_passkeyAuth->authState()) + || (currentAuthCustom() && currentAuthCustom()->authState() == AS_Success)) { + if (m_faceAuth) m_faceAuth->setAuthState(AS_Ended, "Ended"); + if (m_irisAuth) m_irisAuth->setAuthState(AS_Ended, "Ended"); + // 认证拦截,接入域管二级以上因子 + if (m_model->currentUser()->isLdapUser() && LPUtil::loginType() == LPUtil::Type::CLT_MFA) { + if (currentAuthCustom() && currentAuthCustom()->authState() == AS_Success) { + emit authFinished(); + } else if (LPUtil::hasSecondLevel(m_model->currentUser()->name())){ + initCustomMFAAuth(); + } else { + emit authFinished(); + } + } else { + emit authFinished(); + } + } +} + +void SFAWidget::removeAuthButton(AuthCustom *auth) +{ + if (!auth) + return; + + auto btn = m_authButtons.value(auth->customAuthType()); + if (btn) { + btn->deleteLater(); + m_authButtons.remove(auth->customAuthType()); + } +} diff --git a/src/session-widgets/sfa_widget.h b/src/session-widgets/sfa_widget.h index 7f0e0fc9..1de2d6e6 100644 --- a/src/session-widgets/sfa_widget.h +++ b/src/session-widgets/sfa_widget.h @@ -1,29 +1,15 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef SFAWIDGET_H #define SFAWIDGET_H #include "auth_widget.h" #include "userinfo.h" +#include "authcommon.h" +#include "buttonbox.h" +#include "assist_login_widget.h" #include #include @@ -35,7 +21,6 @@ #include class AuthModule; -class KbLayoutWidget; class KeyboardMonitor; class DLineEditEx; @@ -49,50 +34,73 @@ class SFAWidget : public AuthWidget public: explicit SFAWidget(QWidget *parent = nullptr); + ~SFAWidget(); void setModel(const SessionBaseModel *model) override; - void setAuthType(const int type) override; - void setAuthState(const int type, const int state, const QString &message) override; + void setAuthType(const AuthCommon::AuthFlags type) override; + void setAuthState(const AuthCommon::AuthType type, const AuthCommon::AuthState state, const QString &message) override; int getTopSpacing() const override; public slots: void onRetryButtonVisibleChanged(bool visible); + void onRequestChangeAuth(AuthCommon::AuthType authType); + void onLightdmPamStartChanged(); protected: void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; +protected Q_SLOTS: + void updateBlurEffectGeometry(); + void onActiveAuth(AuthCommon::AuthType authType); + void onAccountError(); + private: void initUI(); void initConnections(); + void initAuthFactors(const AuthCommon::AuthFlags type); + void initCustomFactors(const AuthCommon::AuthFlags type); + void chooseAuthType(const AuthCommon::AuthFlags authFlags); + void initChooseAuthButtonBox(const AuthCommon::AuthFlags authFlags); void initSingleAuth(); void initPasswdAuth(); void initFingerprintAuth(); + void initPasskeyAuth(); void initUKeyAuth(); void initFaceAuth(); void initIrisAuth(); - void initCustomAuth(); + void initCustomAuth(LoginPlugin* plugin); + void initCustomMFAAuth(); - void checkAuthResult(const int type, const int state) override; + void checkAuthResult(const AuthCommon::AuthType type, const AuthCommon::AuthState state) override; - void syncAuthType(const QVariant &value); void replaceWidget(AuthModule *authModule); void setBioAuthStateVisible(AuthModule *authModule, bool visible); void updateSpaceItem(); void updateFocus(); + void initAccount(); + bool useCustomAuth() const; + bool showAuthButtonBox() const; + void sendAuthFinished(); + QList filtrateAuthPlugins(const QList &plugins) const; + AuthCustom *currentAuthCustom() const; + void removeAuthButton(AuthCustom *auth); private: QVBoxLayout *m_mainLayout; - DButtonBox *m_chooseAuthButtonBox; // 认证选择按钮 + ButtonBox *m_chooseAuthButtonBox; // 认证选择按钮 DLabel *m_biometricAuthState; // 生物认证状态 - QMap m_authButtons; DFloatingButton *m_retryButton; QSpacerItem *m_bioAuthStatePlaceHolder; QSpacerItem *m_bioBottomSpacingHolder; QSpacerItem *m_authTypeBottomSpacingHolder; + int m_currentAuthType; + + QMap m_authButtons; + QMap> m_customAuths; }; #endif // SFAWIDGET_H diff --git a/src/session-widgets/user_widget.cpp b/src/session-widgets/user_widget.cpp index c841faec..76ea8c2d 100644 --- a/src/session-widgets/user_widget.cpp +++ b/src/session-widgets/user_widget.cpp @@ -1,33 +1,21 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "user_widget.h" +#include "user_name_widget.h" #include "useravatar.h" +#include "dconfig_helper.h" +#include "constants.h" #include #include const int BlurRadius = 15; const int BlurTransparency = 70; -const int UserNameHeight = 42; +const int UserDisplayNameHeight = 42; + +using namespace DDESESSIONCC; UserWidget::UserWidget(QWidget *parent) : QWidget(parent) @@ -37,8 +25,9 @@ UserWidget::UserWidget(QWidget *parent) , m_blurEffectWidget(new DBlurEffectWidget(this)) , m_avatar(new UserAvatar(this)) , m_loginState(new DLabel(this)) - , m_nameLabel(new DLabel(this)) - , m_nameWidget(new QWidget(this)) + , m_displayNameLabel(new DLabel(this)) + , m_displayNameWidget(new QWidget(this)) + , m_userNameWidget(nullptr) { setObjectName(QStringLiteral("UserWidget")); setAccessibleName(QStringLiteral("UserWidget")); @@ -56,39 +45,85 @@ void UserWidget::initUI() m_avatar->setIcon(m_user->avatar()); m_avatar->setAvatarSize(UserAvatar::AvatarSmallSize); - /* 用户名 */ - m_nameWidget->setAccessibleName(QStringLiteral("NameWidget")); - QHBoxLayout *nameLayout = new QHBoxLayout(m_nameWidget); + /* 用户全名 */ + m_displayNameWidget->setAccessibleName(QStringLiteral("NameWidget")); + QHBoxLayout *nameLayout = new QHBoxLayout(m_displayNameWidget); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) nameLayout->setContentsMargins(0, 0, 0, 0); - nameLayout->setSpacing(5); +#else + nameLayout->setMargin(0); +#endif + nameLayout->addStretch(); QPixmap pixmap = DHiDPIHelper::loadNxPixmap(":/misc/images/select.svg"); pixmap.setDevicePixelRatio(devicePixelRatioF()); m_loginState->setAccessibleName("LoginState"); m_loginState->setPixmap(pixmap); m_loginState->setVisible(m_user->isLogin()); - nameLayout->addWidget(m_loginState, 0, Qt::AlignVCenter | Qt::AlignRight); - - m_nameLabel->setAccessibleName("NameLabel"); - m_nameLabel->setTextFormat(Qt::TextFormat::PlainText); - m_nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_nameLabel->setFixedHeight(UserNameHeight); - m_nameLabel->setText(m_user->displayName()); - DFontSizeManager::instance()->bind(m_nameLabel, DFontSizeManager::T2); - QPalette palette = m_nameLabel->palette(); + QVBoxLayout *loginStateLayout = new QVBoxLayout; + loginStateLayout->setSpacing(0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + loginStateLayout->setContentsMargins(0, 0, 0, 0); +#else + loginStateLayout->setMargin(0); +#endif + loginStateLayout->addSpacing(4); + loginStateLayout->addWidget(m_loginState); + nameLayout->addLayout(loginStateLayout); + + // 域账户标识 + QPixmap domainUserpixmap = QIcon::fromTheme(":/misc/images/domainUser.svg").pixmap(24, 24); + domainUserpixmap.setDevicePixelRatio(devicePixelRatioF()); + DLabel *domainUserLabel = new DLabel(this); + domainUserLabel->setAccessibleName("isDomainUser"); + domainUserLabel->setPixmap(domainUserpixmap); + domainUserLabel->setVisible(m_user->isDomainUser()); + domainUserLabel->setAlignment(Qt::AlignVCenter); + QVBoxLayout *isDomainUserLayout = new QVBoxLayout; + isDomainUserLayout->setContentsMargins(0, 5, 0, 0); + isDomainUserLayout->addWidget(domainUserLabel); + nameLayout->addLayout(isDomainUserLayout); + + m_displayNameLabel->setAccessibleName("NameLabel"); + m_displayNameLabel->setTextFormat(Qt::TextFormat::PlainText); + m_displayNameLabel->setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Fixed); + m_displayNameLabel->setFixedHeight(UserDisplayNameHeight); + m_displayNameLabel->setText(m_user->displayName()); + DFontSizeManager::instance()->bind(m_displayNameLabel, DFontSizeManager::T2); + QPalette palette = m_displayNameLabel->palette(); palette.setColor(QPalette::WindowText, Qt::white); - m_nameLabel->setPalette(palette); - nameLayout->addWidget(m_nameLabel, 1, Qt::AlignVCenter | Qt::AlignLeft); + m_displayNameLabel->setPalette(palette); + nameLayout->addWidget(m_displayNameLabel); + nameLayout->addStretch(); + // 用户名,根据配置决定是否构造对象 + if (DConfigHelper::instance()->getConfig(SHOW_USER_NAME, false).toBool()) { + m_userNameWidget = new UserNameWidget(true, false, this); + m_userNameWidget->updateFullName(m_user->fullName()); + setFixedHeight(heightHint()); + } /* 模糊背景 */ m_blurEffectWidget->setMaskColor(DBlurEffectWidget::LightColor); m_blurEffectWidget->setMaskAlpha(BlurTransparency); m_blurEffectWidget->setBlurRectXRadius(BlurRadius); m_blurEffectWidget->setBlurRectYRadius(BlurRadius); + m_mainLayout->setSpacing(0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_mainLayout->setContentsMargins(0, 0, 0, 0); +#else + m_mainLayout->setMargin(0); +#endif m_mainLayout->addWidget(m_avatar); - m_mainLayout->addWidget(m_nameWidget, 0, Qt::AlignHCenter); + m_mainLayout->addSpacing(4); + m_mainLayout->addWidget(m_displayNameWidget); + if (m_userNameWidget) + m_mainLayout->addWidget(m_userNameWidget); m_mainLayout->addSpacing(20); + m_mainLayout->addStretch(1); + + DConfigHelper::instance()->bind(this, SHOW_USER_NAME, &UserWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, USER_FRAME_MAX_WIDTH, &UserWidget::onDConfigPropertyChanged); } void UserWidget::initConnections() @@ -115,6 +150,11 @@ void UserWidget::setUser(std::shared_ptr user) updateUserNameLabel(); } +const std::shared_ptr &UserWidget::user() const +{ + return m_user; +} + /** * @brief 设置用户选中标识 * @param isSelected @@ -159,16 +199,26 @@ void UserWidget::setAvatar(const QString &avatar) */ void UserWidget::updateUserNameLabel() { - const QString &name = m_user->displayName(); - int nameWidth = m_nameLabel->fontMetrics().boundingRect(name).width(); - int labelMaxWidth = width() - 25 * 2; + const bool showUserName = DConfigHelper::instance()->getConfig(SHOW_USER_NAME, false).toBool(); + const QString &name = showUserName ? m_user->name() : m_user->displayName(); + int nameWidth = m_displayNameLabel->fontMetrics().boundingRect(name).width(); - if (nameWidth > labelMaxWidth) { - QString str = m_nameLabel->fontMetrics().elidedText(name, Qt::ElideRight, labelMaxWidth); - m_nameLabel->setText(str); + //切换账号时,是否显示全部账号 + bool ok; + int userFrameMaxWidth = DConfigHelper::instance()->getConfig(USER_FRAME_MAX_WIDTH, UserFrameWidth).toInt(&ok); + if (!ok) userFrameMaxWidth = UserFrameWidth; + int maxFontWidth = nameWidth + 25 * 2; + int labelMaxWidth = userFrameMaxWidth - 25 * 2; + setFixedWidth(maxFontWidth >= userFrameMaxWidth ? userFrameMaxWidth : maxFontWidth >= UserFrameWidth ? maxFontWidth : UserFrameWidth); + if (maxFontWidth > userFrameMaxWidth) { + QString str = m_displayNameLabel->fontMetrics().elidedText(name, Qt::ElideRight, labelMaxWidth); + m_displayNameLabel->setText(str); } else { - m_nameLabel->setText(name); + m_displayNameLabel->setText(name); } + + if (m_userNameWidget) + m_userNameWidget->updateFullName(m_user->fullName()); } /** @@ -187,7 +237,7 @@ void UserWidget::updateBlurEffectGeometry() { QRect rect = layout()->geometry(); rect.setTop(m_avatar->geometry().top() + m_avatar->height() / 2); - rect.setBottom(m_nameWidget->geometry().bottom() + 10); + rect.setBottom(rect.bottom() - 18); m_blurEffectWidget->setGeometry(rect); } @@ -220,3 +270,44 @@ void UserWidget::resizeEvent(QResizeEvent *event) updateBlurEffectGeometry(); QWidget::resizeEvent(event); } + +int UserWidget::heightHint() const +{ + if (m_userNameWidget) + return UserFrameHeight + m_userNameWidget->heightHint(); + + return UserFrameHeight; +} + +void UserWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + qCInfo(DDE_SHELL) << "DConfig property changed, key: " << key << ", value: " << value; + if (key == SHOW_USER_NAME) { + const bool showUserName = value.toBool(); + if (showUserName) { + if (!obj->m_userNameWidget) { + obj->m_userNameWidget = new UserNameWidget(true, false, obj); + } + obj->m_mainLayout->insertWidget(obj->m_mainLayout->indexOf(obj->m_displayNameWidget) + 1, obj->m_userNameWidget); + obj->m_userNameWidget->show(); + if (obj->m_user) + obj->m_userNameWidget->updateFullName(obj->m_user->fullName()); + + } else { + if (obj->m_userNameWidget) { + delete obj->m_userNameWidget; + obj->m_userNameWidget = nullptr; + } + } + } + + // 刷新界面 + obj->updateUserNameLabel(); + obj->setFixedHeight(obj->heightHint()); + obj->updateBlurEffectGeometry(); + obj->update(); +} diff --git a/src/session-widgets/user_widget.h b/src/session-widgets/user_widget.h index bccf51dc..8e07b498 100644 --- a/src/session-widgets/user_widget.h +++ b/src/session-widgets/user_widget.h @@ -1,28 +1,12 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef USERWIDGET_H #define USERWIDGET_H #include "userinfo.h" +#include "user_name_widget.h" #include #include @@ -43,6 +27,7 @@ class UserWidget : public QWidget explicit UserWidget(QWidget *parent = nullptr); void setUser(std::shared_ptr user); + const std::shared_ptr & user() const; inline bool isSelected() const { return m_isSelected; } void setSelected(bool isSelected); @@ -50,10 +35,13 @@ class UserWidget : public QWidget inline uint uid() const { return m_uid; } void setUid(const uint uid); + int heightHint() const; + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); signals: void clicked(); + protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; @@ -79,9 +67,10 @@ class UserWidget : public QWidget DBlurEffectWidget *m_blurEffectWidget; // 模糊背景 UserAvatar *m_avatar; // 用户头像 - DLabel *m_loginState; // 用户登录状态 - DLabel *m_nameLabel; // 用户名 - QWidget *m_nameWidget; // 用户名控件 + DLabel *m_loginState; // 用户登录状态 + DLabel *m_displayNameLabel; // 用户全名 + QWidget *m_displayNameWidget; // 用户全名控件 + UserNameWidget *m_userNameWidget; // 用户名 std::shared_ptr m_user; }; diff --git a/src/session-widgets/userframelist.cpp b/src/session-widgets/userframelist.cpp index 65634b54..685a7c1f 100644 --- a/src/session-widgets/userframelist.cpp +++ b/src/session-widgets/userframelist.cpp @@ -1,31 +1,15 @@ -/* - * Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: lixin - * - * Maintainer: lixin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "userframelist.h" +#include "dconfig_helper.h" #include "dflowlayout.h" -#include "framedatabind.h" #include "sessionbasemodel.h" #include "user_widget.h" #include "userinfo.h" +#include "constants.h" #include #include @@ -33,12 +17,13 @@ #include #include -const int UserFrameSpaceing = 40; +const int UserFrameSpacing = 40; + +using namespace DDESESSIONCC; UserFrameList::UserFrameList(QWidget *parent) : QWidget(parent) , m_scrollArea(new QScrollArea(this)) - , m_frameDataBind(FrameDataBind::Instance()) { setObjectName(QStringLiteral("UserFrameList")); setAccessibleName(QStringLiteral("UserFrameList")); @@ -54,18 +39,13 @@ UserFrameList::UserFrameList(QWidget *parent) QScrollerProperties sp; sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootWhenScrollable); scroller->setScrollerProperties(sp); - - std::function function = std::bind(&UserFrameList::onOtherPageChanged, this, std::placeholders::_1); - int index = m_frameDataBind->registerFunction("UserFrameList", function); - - connect(this, &UserFrameList::destroyed, this, [this, index] { - m_frameDataBind->unRegisterFunction("UserFrameList", index); - }); + DConfigHelper::instance()->bind(this, SHOW_USER_NAME, &UserFrameList::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, USER_FRAME_MAX_WIDTH, &UserFrameList::onDConfigPropertyChanged); } void UserFrameList::initUI() { - m_centerWidget = new QWidget; + m_centerWidget = new QWidget(this); m_centerWidget->setAccessibleName("UserFrameListCenterWidget"); m_flowLayout = new DFlowLayout(m_centerWidget); @@ -93,6 +73,10 @@ void UserFrameList::setModel(SessionBaseModel *model) connect(model, &SessionBaseModel::userAdded, this, &UserFrameList::handlerBeforeAddUser); connect(model, &SessionBaseModel::userRemoved, this, &UserFrameList::removeUser); + if (m_model->appType() == AppType::Login) { + // 处理greeter用户增删信号阻塞问题 + connect(model, &SessionBaseModel::userListChanged, this, &UserFrameList::onUserListChanged); + } QList> userList = m_model->userList(); for (auto user : userList) { @@ -104,7 +88,7 @@ void UserFrameList::setFixedSize(const QSize &size) { QWidget::setFixedSize(size); //先确定界面大小,再根据界面大小计算用户列表区域大小 - updateLayout(); + updateLayout(width()); } void UserFrameList::handlerBeforeAddUser(std::shared_ptr user) @@ -135,20 +119,20 @@ void UserFrameList::addUser(const std::shared_ptr user) //多用户的情况按照其uid排序,升序排列,符合账户先后创建顺序 m_loginWidgets.push_back(widget); - qSort(m_loginWidgets.begin(), m_loginWidgets.end(), [=](UserWidget *w1, UserWidget *w2) { + std::sort(m_loginWidgets.begin(), m_loginWidgets.end(), [](UserWidget *w1, UserWidget *w2) { return (w1->uid() < w2->uid()); }); int index = m_loginWidgets.indexOf(widget); m_flowLayout->insertWidget(index, widget); //添加用户和删除用户时,重新计算区域大小 - updateLayout(); + updateLayout(width()); } //删除用户 void UserFrameList::removeUser(const std::shared_ptr user) { - qDebug() << "UserFrameList::removeUser:" << user->path(); + qCDebug(DDE_SHELL) << "User frame list remove user:" << user->path(); foreach (auto w, m_loginWidgets) { if (w->uid() == user->uid()) { m_loginWidgets.removeOne(w); @@ -162,7 +146,7 @@ void UserFrameList::removeUser(const std::shared_ptr user) } //添加用户和删除用户时,重新计算区域大小 - updateLayout(); + updateLayout(width()); } //点击用户 @@ -194,12 +178,11 @@ void UserFrameList::switchNextUser() currentSelectedUser->setSelected(true); //处理m_scrollArea翻页显示 m_scrollArea->verticalScrollBar()->setValue(0); - m_frameDataBind->updateValue("UserFrameList", currentSelectedUser->uid()); } else { //处理m_scrollArea翻页显示 int selectedRight = m_loginWidgets[i]->geometry().right(); int scrollRight = m_scrollArea->widget()->geometry().right(); - if (selectedRight + UserFrameSpaceing == scrollRight) { + if (selectedRight + UserFrameSpacing == scrollRight) { QPoint topLeft; if (m_rowCount == 1) { topLeft = m_loginWidgets[i + 1]->geometry().topLeft(); @@ -211,7 +194,6 @@ void UserFrameList::switchNextUser() currentSelectedUser = m_loginWidgets[i + 1]; currentSelectedUser->setSelected(true); - m_frameDataBind->updateValue("UserFrameList", currentSelectedUser->uid()); } break; } @@ -231,7 +213,6 @@ void UserFrameList::switchPreviousUser() currentSelectedUser->setSelected(true); //处理m_scrollArea翻页显示 m_scrollArea->verticalScrollBar()->setValue(m_scrollArea->verticalScrollBar()->maximum()); - m_frameDataBind->updateValue("UserFrameList", currentSelectedUser->uid()); } else { //处理m_scrollArea翻页显示 QPoint topLeft = m_loginWidgets[i]->geometry().topLeft(); @@ -241,7 +222,6 @@ void UserFrameList::switchPreviousUser() currentSelectedUser = m_loginWidgets[i - 1]; currentSelectedUser->setSelected(true); - m_frameDataBind->updateValue("UserFrameList", currentSelectedUser->uid()); } break; } @@ -255,20 +235,60 @@ void UserFrameList::onOtherPageChanged(const QVariant &value) } } -void UserFrameList::updateLayout() +void UserFrameList::onUserListChanged(const QList > &list) { - //处理窗体数量小于5个时的居中显示,取 窗体数量*窗体宽度 和 最大宽度 的较小值,设置为m_centerWidget的宽度 - int count = m_flowLayout->count(); - if (count < 5 && count > 0) { - m_scrollArea->setFixedSize((UserFrameWidth + UserFrameSpaceing) * count, UserFrameHeight + 20); + qDeleteAll(m_loginWidgets); + m_loginWidgets.clear(); + currentSelectedUser = nullptr; + + foreach(auto user, list) { + handlerBeforeAddUser(user); + } +} + +void UserFrameList::updateLayout(int width) +{ + // 处理窗体数量小于5个时的居中显示,取 窗体数量*窗体宽度 和 最大宽度 的较小值,设置为m_centerWidget的宽度 + auto userWidget = m_loginWidgets.constFirst(); + int userWidgetHeight = userWidget ? userWidget->heightHint() : UserFrameHeight; + + int resolutionWidth = 0; + QWidget* parentWidget = qobject_cast(this->parent()); + if (parentWidget) + resolutionWidth = parentWidget->width(); + + // 根据界面总宽度计算第一行可以显示多少用户信息 + int countWidth = 0; + int count = 0; + for (auto w : m_loginWidgets) { + countWidth += w->width() + UserFrameSpacing; + count += 1; + if (count > 5 || countWidth > resolutionWidth - 200 * 2) { + countWidth -= w->width() + UserFrameSpacing; + count -= 1; + break; + } } - if (count >= 5) { - m_scrollArea->setFixedSize((UserFrameWidth + UserFrameSpaceing) * 5, (UserFrameHeight + UserFrameSpaceing) * 2); + + if (countWidth > 0) { + if (m_flowLayout->count() <= count) { + m_scrollArea->setFixedSize(countWidth, userWidgetHeight + 20); + // 单行用户时,限制高度避免滚动条 + m_centerWidget->setMaximumHeight(m_scrollArea->height()); + } else { + m_scrollArea->setFixedSize(countWidth, (userWidgetHeight + UserFrameSpacing) * 2); + // 多行用户时,清除高度限制,让内容自适应以支持滚动 + m_centerWidget->setMaximumHeight(QWIDGETSIZE_MAX); + } + + m_centerWidget->setFixedWidth(m_scrollArea->width() - 10); } - m_centerWidget->setFixedWidth(m_scrollArea->width() - 10); + // 设置当前选中用户 std::shared_ptr user = m_model->currentUser(); - if (user.get() == nullptr) return; + if (user.get() == nullptr) + return; + for (auto it = m_loginWidgets.constBegin(); it != m_loginWidgets.constEnd(); ++it) { auto login_widget = *it; @@ -331,7 +351,20 @@ void UserFrameList::focusOutEvent(QFocusEvent *event) void UserFrameList::resizeEvent(QResizeEvent *event) { - updateLayout(); - QWidget::resizeEvent(event); + updateLayout(width()); +} + +void UserFrameList::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject* objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == SHOW_USER_NAME || key == USER_FRAME_MAX_WIDTH) { + // 需要等待UserWidget处理完,延时100ms后更新布局 + QTimer::singleShot(100, obj, [obj]{ + obj->updateLayout(obj->width()); + }); + } } diff --git a/src/session-widgets/userframelist.h b/src/session-widgets/userframelist.h index 37965328..4f0943a8 100644 --- a/src/session-widgets/userframelist.h +++ b/src/session-widgets/userframelist.h @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: lixin - * - * Maintainer: lixin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef USERFRAMELIST_H #define USERFRAMELIST_H @@ -32,7 +15,6 @@ class UserWidget; class User; class SessionBaseModel; -class FrameDataBind; class QVBoxLayout; class QScrollArea; @@ -45,7 +27,8 @@ class UserFrameList : public QWidget explicit UserFrameList(QWidget *parent = nullptr); void setModel(SessionBaseModel *model); void setFixedSize(const QSize &size); - void updateLayout(); + void updateLayout(int width); + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject* objPtr); signals: void requestSwitchUser(std::shared_ptr user); @@ -67,6 +50,7 @@ class UserFrameList : public QWidget void switchNextUser(); void switchPreviousUser(); void onOtherPageChanged(const QVariant &value); + void onUserListChanged(const QList > &list); private: QScrollArea *m_scrollArea; @@ -75,9 +59,7 @@ class UserFrameList : public QWidget QMap m_userWidgets; QPointer currentSelectedUser; SessionBaseModel *m_model; - FrameDataBind *m_frameDataBind; QWidget *m_centerWidget; - int m_colCount; int m_rowCount; }; diff --git a/src/session-widgets/userinfo.cpp b/src/session-widgets/userinfo.cpp index 3be87d2f..83fa12d5 100644 --- a/src/session-widgets/userinfo.cpp +++ b/src/session-widgets/userinfo.cpp @@ -1,38 +1,25 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "userinfo.h" - +#include "dconfig_helper.h" #include "constants.h" #include #include #include -#include + +#include "dbusconstant.h" #define DEFAULT_AVATAR ":/img/default_avatar.svg" #define DEFAULT_BACKGROUND "/usr/share/backgrounds/default_background.jpg" +using namespace DDESESSIONCC; + User::User(QObject *parent) : QObject(parent) + , m_accountType(Administrator) , m_isAutomaticLogin(false) , m_isLogin(false) , m_isNoPasswordLogin(false) @@ -40,7 +27,7 @@ User::User(QObject *parent) , m_isUse24HourFormat(true) , m_expiredDayLeft(0) , m_expiredState(ExpiredNormal) - , m_lastAuthType(0) + , m_lastAuthType(AuthCommon::AT_Password) , m_shortDateFormat(0) , m_shortTimeFormat(0) , m_weekdayFormat(0) @@ -56,6 +43,7 @@ User::User(QObject *parent) User::User(const User &user) : QObject(user.parent()) + , m_accountType(user.m_accountType) , m_isAutomaticLogin(user.m_isAutomaticLogin) , m_isLogin(user.m_isLogin) , m_isNoPasswordLogin(user.m_isNoPasswordLogin) @@ -63,7 +51,7 @@ User::User(const User &user) , m_isUse24HourFormat(user.m_isUse24HourFormat) , m_expiredDayLeft(user.m_expiredDayLeft) , m_expiredState(user.m_expiredState) - , m_lastAuthType(0) + , m_lastAuthType(AuthCommon::AT_Password) , m_shortDateFormat(user.m_shortDateFormat) , m_shortTimeFormat(user.m_shortTimeFormat) , m_weekdayFormat(user.m_weekdayFormat) @@ -78,6 +66,7 @@ User::User(const User &user) , m_desktopBackgrounds(user.m_desktopBackgrounds) , m_keyboardLayoutList(user.m_keyboardLayoutList) , m_limitsInfo(new QMap(*user.m_limitsInfo)) + , m_groups(user.groups()) { } @@ -91,6 +80,39 @@ bool User::operator==(const User &user) const return user.uid() == m_uid && user.name() == m_name; } +/** + * @brief 检查用户是否是LDAP用户 + * @return true 是 false 否 + */ +bool User::isLdapUser() +{ + struct group *grp = getgrnam("udcp"); + if (!grp) { + return false; + } + + for (char **member = grp->gr_mem; member && *member; ++member) { + if (*member == m_name) { + return true; + } + } + return false; +} + +bool User::isDomainUser() +{ + /* 域账户判断条件: + * 1.用户组包含“domain”(外部Linux上游) + * 2.用户组包含“udcp” 且 uid大于10000(统信域管) + * 3.用户组包含“domain users”且uid大于10000(windows AD域) + */ + bool isDomainUser = this->groups().contains("domain") + || (this->groups().contains("udcp") && this->uid() > 10000) + || (this->groups().contains("domain users") && this->uid() > 10000); + + return this->isUserValid() && isDomainUser; +} + /** * @brief 更新登录状态 * @@ -122,6 +144,7 @@ void User::updateLimitsInfo(const QString &info) limitsInfoTmp.numFailures = limitsInfoObj["numFailures"].toVariant().toUInt(); limitsInfoTmp.locked = limitsInfoObj["locked"].toBool(); limitsInfoTmp.unlockTime = limitsInfoObj["unlockTime"].toString(); + limitsInfoTmp.flag = limitsInfoObj["flag"].toInt(); m_limitsInfo->insert(limitsInfoObj["flag"].toInt(), limitsInfoTmp); } emit limitsInfoChanged(m_limitsInfo); @@ -132,7 +155,7 @@ void User::updateLimitsInfo(const QString &info) * * @param type */ -void User::setLastAuthType(const int type) +void User::setLastAuthType(const AuthCommon::AuthType type) { if (m_lastAuthType == type) { return; @@ -140,6 +163,18 @@ void User::setLastAuthType(const int type) m_lastAuthType = type; } +void User::updatePasswordExpiredState(User::ExpiredState state, int dayLeft) +{ + m_expiredState = state; + m_expiredDayLeft = dayLeft; + emit passwordExpiredInfoChanged(); +} + +bool User::allowToChangePassword() const +{ + return m_accountType == Administrator || DConfigHelper::instance()->getConfig(CHANGE_PASSWORD_FOR_NORMAL_USER, true).toBool() || m_expiredState != ExpiredAlready; +} + bool User::checkUserIsNoPWGrp(const User *user) const { if (user->type() == User::ADDomain) { @@ -157,7 +192,7 @@ bool User::checkUserIsNoPWGrp(const User *user) const /* Fetch passwd structure (contains first group ID for user) */ pw = getpwnam(user->name().toUtf8().data()); if (pw == nullptr) { - qDebug() << "fetch passwd structure failed, username: " << user->name(); + qCDebug(DDE_SHELL) << "Fetch password structure failed, username: " << user->name(); return false; } @@ -208,7 +243,7 @@ QString User::userPwdName(const uid_t uid) const NativeUser::NativeUser(const QString &path, QObject *parent) : User(parent) , m_path(path) - , m_userInter(new UserInter("com.deepin.daemon.Accounts", path, QDBusConnection::systemBus(), this)) + , m_userInter(new UserInter(DSS_DBUS::accountsService, path, QDBusConnection::systemBus(), this)) { initConnections(); initData(); @@ -217,8 +252,8 @@ NativeUser::NativeUser(const QString &path, QObject *parent) NativeUser::NativeUser(const uid_t &uid, QObject *parent) : User(parent) - , m_path("/com/deepin/daemon/Accounts/User" + QString::number(uid)) - , m_userInter(new UserInter("com.deepin.daemon.Accounts", m_path, QDBusConnection::systemBus(), this)) + , m_path(QString(DSS_DBUS::accountsUserPath).arg(QString::number(uid))) + , m_userInter(new UserInter(DSS_DBUS::accountsService, m_path, QDBusConnection::systemBus(), this)) { initConnections(); initData(); @@ -228,7 +263,7 @@ NativeUser::NativeUser(const uid_t &uid, QObject *parent) NativeUser::NativeUser(const NativeUser &user) : User(user) , m_path(user.path()) - , m_userInter(new UserInter("com.deepin.daemon.Accounts", m_path, QDBusConnection::systemBus(), this)) + , m_userInter(new UserInter(DSS_DBUS::accountsService, m_path, QDBusConnection::systemBus(), this)) { initConnections(); } @@ -246,7 +281,6 @@ void NativeUser::initConnections() connect(m_userInter, &UserInter::NoPasswdLoginChanged, this, &NativeUser::updateNoPasswordLogin); connect(m_userInter, &UserInter::PasswordHintChanged, this, &NativeUser::updatePasswordHint); connect(m_userInter, &UserInter::PasswordStatusChanged, this, &NativeUser::updatePasswordState); - connect(m_userInter, &UserInter::PasswordHintChanged, this, &NativeUser::updatePasswordHint); connect(m_userInter, &UserInter::ShortDateFormatChanged, this, &NativeUser::updateShortDateFormat); connect(m_userInter, &UserInter::ShortTimeFormatChanged, this, &NativeUser::updateShortTimeFormat); connect(m_userInter, &UserInter::WeekdayFormatChanged, this, &NativeUser::updateWeekdayFormat); @@ -255,6 +289,7 @@ void NativeUser::initConnections() connect(m_userInter, &UserInter::Use24HourFormatChanged, this, &NativeUser::updateUse24HourFormat); connect(m_userInter, &UserInter::PasswordLastChangeChanged, this, &NativeUser::updatePasswordExpiredInfo); connect(m_userInter, &UserInter::MaxPasswordAgeChanged, this, &NativeUser::updatePasswordExpiredInfo); + connect(m_userInter, &UserInter::AccountTypeChanged, this, &NativeUser::updateAccountType); } void NativeUser::initData() @@ -263,19 +298,19 @@ void NativeUser::initData() m_isNoPasswordLogin = m_userInter->noPasswdLogin(); m_isPasswordValid = (m_userInter->passwordStatus() == "P"); m_isUse24HourFormat = m_userInter->use24HourFormat(); - m_expiredState = m_userInter->PasswordExpiredInfo(m_expiredDayLeft).value(); m_shortDateFormat = m_userInter->shortDateFormat(); m_shortTimeFormat = m_userInter->shortTimeFormat(); m_weekdayFormat = m_userInter->weekdayFormat(); + m_groups = m_userInter->groups(); const QString avatarPath = toLocalFile(m_userInter->iconFile()); - if (!avatarPath.isEmpty() && QFile(avatarPath).exists() && QFile(avatarPath).size() && QImageReader(avatarPath).canRead()) { + if (!avatarPath.isEmpty() && QFile(avatarPath).exists() && QFile(avatarPath).size() && checkPictureCanRead(avatarPath)) { m_avatar = avatarPath; } m_fullName = m_userInter->fullName(); const QString backgroundPath = toLocalFile(m_userInter->greeterBackground()); - if (!backgroundPath.isEmpty() && QFile(backgroundPath).exists() && QFile(backgroundPath).size() && QImageReader(backgroundPath).canRead()) { + if (!backgroundPath.isEmpty() && QFile(backgroundPath).exists() && QFile(backgroundPath).size() && checkPictureCanRead(backgroundPath)) { m_greeterBackground = backgroundPath; } m_keyboardLayout = m_userInter->layout(); @@ -285,6 +320,15 @@ void NativeUser::initData() m_desktopBackgrounds = m_userInter->desktopBackgrounds(); m_keyboardLayoutList = m_userInter->historyLayout(); m_uid = m_userInter->uid().toUInt(); + m_accountType = m_userInter->accountType(); + + qCDebug(DDE_SHELL) << "Init data, user name:" << m_userInter->userName() + << ", Is no password login:" << m_isNoPasswordLogin + << ", Is auto login:" << m_isAutomaticLogin + << ", Is password valid:" << m_isPasswordValid + << ", Password expired state:" << m_expiredState + << ", Locale:" << m_locale + << ", AccountType:" << m_userInter->accountType(); } /** @@ -306,7 +350,7 @@ void NativeUser::initConfiguration(const QString &config) if (desktopBackgrounds.size() >= index && index > 0) { // m_desktopBackgrounds = toLocalFile(desktopBackgrounds.at(index - 1)); } else { - qDebug() << "configAccountInfo get error index:" << index << ", backgrounds:" << desktopBackgrounds; + qCDebug(DDE_SHELL) << "configAccountInfo get error index:" << index << ", backgrounds:" << desktopBackgrounds; } } @@ -332,7 +376,7 @@ void NativeUser::updateAvatar(const QString &path) return; } - if (!pathTmp.isEmpty() && QFile(pathTmp).exists() && QFile(pathTmp).size() && QImageReader(pathTmp).canRead()) { + if (!pathTmp.isEmpty() && QFile(pathTmp).exists() && QFile(pathTmp).size() && checkPictureCanRead(pathTmp)) { m_avatar = pathTmp; } else { m_avatar = DEFAULT_AVATAR; @@ -347,6 +391,7 @@ void NativeUser::updateAvatar(const QString &path) */ void NativeUser::updateAutomaticLogin(const bool autoLoginState) { + qCInfo(DDE_SHELL) << "Update automatic login: " << autoLoginState; if (autoLoginState == m_isAutomaticLogin) { return; } @@ -371,7 +416,7 @@ void NativeUser::updateDesktopBackgrounds(const QStringList &backgrounds) // m_desktopBackgrounds = toLocalFile(backgrounds.at(index - 1)); // emit desktopBackgroundChanged(m_desktopBackgrounds); } else { - qDebug() << "DesktopBackgroundsChanged get error index:" << index << ", paths:" << backgrounds; + qCDebug(DDE_SHELL) << "DesktopBackgroundsChanged get error index:" << index << ", paths:" << backgrounds; } } @@ -397,6 +442,10 @@ void NativeUser::updateFullName(const QString &fullName) void NativeUser::updateGreeterBackground(const QString &path) { const QString pathTmp = toLocalFile(path); + if (pathTmp.isEmpty() || !QFile(pathTmp).exists() || !QFile(pathTmp).size() || !checkPictureCanRead(pathTmp)) { + qCWarning(DDE_SHELL) << "Update greeter background, path is invalid: " << pathTmp; + return; + } if (pathTmp == m_greeterBackground) { return; } @@ -467,6 +516,7 @@ void NativeUser::updateName(const QString &name) */ void NativeUser::updateNoPasswordLogin(const bool isNoPasswordLogin) { + qCInfo(DDE_SHELL) << "Update user no password login flag: " << isNoPasswordLogin; if (isNoPasswordLogin == m_isNoPasswordLogin) { return; } @@ -495,10 +545,45 @@ void NativeUser::updatePasswordHint(const QString &hint) void NativeUser::updatePasswordExpiredInfo() { m_expiredState = m_userInter->PasswordExpiredInfo(m_expiredDayLeft).value(); + qCInfo(DDE_SHELL) << "User expired state: " << m_expiredState << ", expired day left: " << m_expiredDayLeft; emit passwordExpiredInfoChanged(); } +/** + * @brief 更新账户的所有信息 + */ +void NativeUser::updateUserInfo() +{ + qCDebug(DDE_SHELL) << "Update user info"; + if (!m_userInter) { + qCWarning(DDE_SHELL) << "User interface is null"; + return; + } + updateAutomaticLogin(m_userInter->automaticLogin()); + updateNoPasswordLogin(m_userInter->noPasswdLogin()); + updatePasswordState(m_userInter->passwordStatus()); + updateUse24HourFormat(m_userInter->use24HourFormat()); + updatePasswordExpiredInfo(); + updateShortDateFormat(m_userInter->shortDateFormat()); + updateShortTimeFormat(m_userInter->shortTimeFormat()); + updateWeekdayFormat(m_userInter->weekdayFormat()); + updateAvatar(m_userInter->iconFile()); + updateFullName(m_userInter->fullName()); + updateGreeterBackground(m_userInter->greeterBackground()); + updateKeyboardLayout(m_userInter->layout()); + updateLocale(m_userInter->locale()); + updatePasswordHint(m_userInter->passwordHint()); + updateKeyboardLayoutList(m_userInter->historyLayout()); + updateAccountType(); +} + +void NativeUser::updateAccountType() +{ + m_accountType = m_userInter->accountType(); + qCInfo(DDE_SHELL) << "User account type: " << m_accountType; +} + /** * @brief 更新密码状态,用户是否设置了密码 * @@ -507,6 +592,7 @@ void NativeUser::updatePasswordExpiredInfo() void NativeUser::updatePasswordState(const QString &state) { const bool isPasswordValidTmp = state == "P" ? true : false; + qCInfo(DDE_SHELL) << "Password state: " << isPasswordValidTmp; if (isPasswordValidTmp == m_isPasswordValid) { return; } diff --git a/src/session-widgets/userinfo.h b/src/session-widgets/userinfo.h index 2d2d4f2e..1e9b20b8 100644 --- a/src/session-widgets/userinfo.h +++ b/src/session-widgets/userinfo.h @@ -1,40 +1,33 @@ -/* -* Copyright (C) 2021 ~ 2021 Uniontech Software Technology Co.,Ltd. -* -* Author: Zhang Qipeng -* -* Maintainer: Zhang Qipeng -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef USERINFO_H #define USERINFO_H #include "constants.h" #include "public_func.h" +#include "authcommon.h" #include +#include +#ifndef ENABLE_DSS_SNIPE #include - using UserInter = com::deepin::daemon::accounts::User; - +#else +#include "userinterface.h" +using UserInter = org::deepin::dde::accounts1::User; +#endif class User : public QObject { Q_OBJECT public: + enum AccountType { + NormalUser, + Administrator + }; + enum UserType { Native, ADDomain, @@ -50,10 +43,23 @@ class User : public QObject struct LimitsInfo { bool reserved[3]; // 用于内存对齐 bool locked; // 认证锁定状态 --- true: 锁定 false: 解锁 + int flag; // 认证类型 uint maxTries; // 最大重试次数 uint numFailures; // 失败次数,一直累加 uint unlockSecs; // 本次锁定总解锁时间(秒),不会随着时间推移减少 QString unlockTime; // 解锁时间(本地时间) + + inline QJsonObject toJson() const + { + QJsonObject obj; + obj["Locked"] = locked; + obj["Flag"] = flag; + obj["MaxTries"] = static_cast(maxTries); + obj["NumFailures"] = static_cast(numFailures); + obj["UnlockSecs"] = static_cast(unlockSecs);; + obj["UnlockTime"] = unlockTime; + return obj; + } }; explicit User(QObject *parent = nullptr); @@ -62,6 +68,10 @@ class User : public QObject bool operator==(const User &user) const; + inline int accountType() const { return m_accountType; } + bool isLdapUser(); + bool isDomainUser(); + inline bool isAutomaticLogin() const { return m_isAutomaticLogin; } inline bool isPasswordValid() const { return m_isPasswordValid; } inline bool isLogin() const { return m_isLogin; } @@ -71,7 +81,7 @@ class User : public QObject inline int expiredDayLeft() const { return m_expiredDayLeft; } inline int expiredState() const { return m_expiredState; } - inline int lastAuthType() const { return m_lastAuthType; } + inline AuthCommon::AuthType lastAuthType() const { return m_lastAuthType; } inline int shortDateFormat() const { return m_shortDateFormat; } inline int shortTimeFormat() const { return m_shortTimeFormat; } inline int weekdayFormat() const { return m_weekdayFormat; } @@ -91,13 +101,19 @@ class User : public QObject inline QStringList desktopBackgrounds() const { return m_desktopBackgrounds; } inline QStringList keyboardLayoutList() const { return m_keyboardLayoutList; } inline uid_t uid() const { return m_uid; } + inline QStringList groups() const { return m_groups; } + inline QString lastCustomAuth() const { return m_lastCustomAuth; } void updateLimitsInfo(const QString &info); void updateLoginState(const bool isLogin); - void setLastAuthType(const int type); + void setLastAuthType(const AuthCommon::AuthType type); + void setLastCustomAuth(const QString &key) { m_lastCustomAuth = key; } + bool allowToChangePassword() const; virtual void setKeyboardLayout(const QString &keyboard) { Q_UNUSED(keyboard) } virtual void updatePasswordExpiredInfo() { } + virtual void updatePasswordExpiredState(ExpiredState state, int dayLeft); + virtual void updateUserInfo() { } signals: void avatarChanged(const QString &); @@ -125,6 +141,7 @@ class User : public QObject QString userPwdName(const uid_t uid) const; protected: + int m_accountType; // 账户类型 bool m_isAutomaticLogin; // 自动登录 bool m_isLogin; // 登录状态 bool m_isNoPasswordLogin; // 无密码登录 @@ -132,7 +149,7 @@ class User : public QObject bool m_isUse24HourFormat; // 24小时制 int m_expiredDayLeft; // 密码过期剩余天数 int m_expiredState; // 密码过期状态 - int m_lastAuthType; // 上次成功的认证 + AuthCommon::AuthType m_lastAuthType; // 上次成功的认证 int m_shortDateFormat; // 短日期格式 int m_shortTimeFormat; // 短时间格式 int m_weekdayFormat; // 星期显示格式 @@ -144,9 +161,11 @@ class User : public QObject QString m_locale; // 语言环境 QString m_name; // 用户名 QString m_passwordHint; // 密码提示 + QString m_lastCustomAuth; // 上次成功的认证插件的 key QStringList m_desktopBackgrounds; // 桌面背景(不同工作区壁纸不同,故是个 List) QStringList m_keyboardLayoutList; // 键盘布局列表 QMap *m_limitsInfo; // 认证限制信息 + QStringList m_groups; // 用户组 }; class NativeUser : public User @@ -165,6 +184,7 @@ class NativeUser : public User void setKeyboardLayout(const QString &keyboard) override; void updatePasswordExpiredInfo() override; + virtual void updateUserInfo() override; private slots: void updateAvatar(const QString &path); @@ -184,6 +204,7 @@ private slots: void updateWeekdayFormat(const int format); void updateUid(const QString &uid); void updateUse24HourFormat(const bool is24HourFormat); + void updateAccountType(); private: void initConnections(); diff --git a/src/session-widgets/userpanel.cpp b/src/session-widgets/userpanel.cpp new file mode 100644 index 00000000..a50b6426 --- /dev/null +++ b/src/session-widgets/userpanel.cpp @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "userpanel.h" +#include "useravatar.h" + +#include + +#include + +UserPanel::UserPanel(QWidget *parent) + : ActionWidget(parent) + , m_isSelected(false) + , m_uid(UINT_MAX) + , m_mainLayout(new QHBoxLayout(this)) + , m_avatar(new UserAvatar(this)) + , m_displayNameLabel(new DLabel(this)) + , m_typeLabel(new DLabel(this)) +{ + setObjectName(QStringLiteral("UserPanel")); + setAccessibleName(QStringLiteral("UserPanel")); + + setFixedSize(UserPanelWidth, UserPanelHeight); + setFocusPolicy(Qt::NoFocus); + initUI(); +} + +void UserPanel::initUI() +{ + setRadius(18); + m_displayNameLabel->setAlignment(Qt::AlignLeft); + DFontSizeManager::instance()->bind(m_displayNameLabel, DFontSizeManager::T5); + m_displayNameLabel->setElideMode(Qt::ElideRight); + + m_typeLabel->setAlignment(Qt::AlignLeft); + DFontSizeManager::instance()->bind(m_typeLabel, DFontSizeManager::T6); + m_typeLabel->setElideMode(Qt::ElideRight); + + m_avatar->setAvatarSize(UserAvatarSize); + m_mainLayout->setSpacing(12); + m_mainLayout->setContentsMargins(10, 10, 10, 10); + QWidget *rightWidget = new QWidget; + QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget); + rightLayout->setSpacing(0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + rightLayout->setContentsMargins(0, 0, 0, 0); +#else + rightLayout->setMargin(0); +#endif + rightLayout->addStretch(); + rightLayout->addWidget(m_displayNameLabel); + rightLayout->addSpacing(6); + rightLayout->addWidget(m_typeLabel); + rightLayout->addStretch(); + m_mainLayout->addWidget(m_avatar); + m_mainLayout->addWidget(rightWidget); + m_mainLayout->addStretch(); + connect(m_avatar, &UserAvatar::clicked, this, &UserPanel::requestAction); +} + +void UserPanel::setSelected(bool isSelected) +{ + m_isSelected = isSelected; + setState(isSelected ? ActionWidget::Enter : ActionWidget::Leave); + update(); +} + +/** + * @brief 给当前 Widget 设置一个 id,用于排序 + * @param uid + */ +void UserPanel::setUid(const uint uid) +{ + m_uid = uid; +} + +/** + * @brief 设置用户头像 + * @param avatar + */ +void UserPanel::setAvatar(const QString &avatar) +{ + m_avatar->setIcon(avatar); + update(); +} + +void UserPanel::setDisplayName(const QString &name) +{ + m_displayNameLabel->setText(name); + update(); +} + +void UserPanel::setName(const QString &name) +{ + m_name = name; +} + +void UserPanel::setFullName(const QString &name) +{ + m_fullName = name; +} + +void UserPanel::setType(const QString &type) +{ + m_typeLabel->setText(type); + update(); +} diff --git a/src/session-widgets/userpanel.h b/src/session-widgets/userpanel.h new file mode 100644 index 00000000..964a5d16 --- /dev/null +++ b/src/session-widgets/userpanel.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef USERPANEL_H +#define USERPANEL_H + +#include "actionwidget.h" + +#include + +#include + +const int UserPanelWidth = 330; +const int UserPanelHeight = 76; +const int UserAvatarSize = 56; + +class QHBoxLayout; +class UserAvatar; + +DWIDGET_USE_NAMESPACE +class UserPanel : public ActionWidget +{ + Q_OBJECT +public: + explicit UserPanel(QWidget *parent = nullptr); + + inline uint uid() const { return m_uid; } + void setUid(const uint uid); + inline bool isSelected() const { return m_isSelected; } + void setSelected(bool isSelected); + void setAvatar(const QString &avatar); + void setDisplayName(const QString &name); + void setName(const QString &name); + const QString &name() const { return m_name; } + void setFullName(const QString &name); + const QString &fullName() const { return m_fullName; } + void setType(const QString &type); + const QString &type() const { return m_type; } + +private: + void initUI(); + +private: + bool m_isSelected; + uint m_uid; + QHBoxLayout *m_mainLayout; + UserAvatar *m_avatar; + QString m_fullName; + QString m_name; + QString m_type; + DLabel *m_displayNameLabel; + DLabel *m_typeLabel; +}; + +#endif // USERPANEL_H diff --git a/src/session-widgets/userswiththesamename.cpp b/src/session-widgets/userswiththesamename.cpp new file mode 100644 index 00000000..81e2620c --- /dev/null +++ b/src/session-widgets/userswiththesamename.cpp @@ -0,0 +1,289 @@ +// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "userswiththesamename.h" + +#include "sessionbasemodel.h" +#include "userpanel.h" + +#include +#include + +#include +#include + +DWIDGET_USE_NAMESPACE + +const int UserPanelSpacing = 20; + +UsersWithTheSameName::UsersWithTheSameName(SessionBaseModel *model, QWidget *parent) + : QWidget(parent) + , m_model(model) + , m_backButton(new InhibitButton(this)) +{ + setObjectName(QStringLiteral("UsersWithTheSameName")); + setAccessibleName(QStringLiteral("UsersWithTheSameName")); + + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setFocusPolicy(Qt::StrongFocus); + + initUI(); +} + +void UsersWithTheSameName::initUI() +{ + m_backButton->setText(tr("Return")); + const QPixmap &normalBackPixmap = DHiDPIHelper::loadNxPixmap(":/img/back-normal.svg"); + m_backButton->setNormalPixmap(normalBackPixmap); + const QPixmap &hoverBackPixmap = DHiDPIHelper::loadNxPixmap(":/img/back-hover.svg"); + m_backButton->setHoverPixmap(hoverBackPixmap); + m_backButton->setFixedSize(200, 64); + DFontSizeManager::instance()->bind(m_backButton, DFontSizeManager::T4); + + QLabel *tipsLabel = new QLabel(this); + tipsLabel->setWordWrap(false); + tipsLabel->setAlignment(Qt::AlignCenter); + tipsLabel->setText(tr("Please select the account for login")); + DFontSizeManager::instance()->bind(tipsLabel, DFontSizeManager::T5); + + m_centerWidget = new QWidget; + m_centerWidget->setAccessibleName("UsersWithTheSameNameCenterWidget"); + + m_panelLayout = new QVBoxLayout(m_centerWidget); + m_panelLayout->setContentsMargins(10, 10, 10, 10); + m_panelLayout->setSpacing(UserPanelSpacing); + + m_centerWidget->setAutoFillBackground(false); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->addStretch(); + mainLayout->addWidget(tipsLabel, 0, Qt::AlignCenter); + mainLayout->addSpacing(40); + mainLayout->addWidget(m_centerWidget, 0, Qt::AlignCenter); + mainLayout->addSpacing(90); + mainLayout->addWidget(m_backButton, 0, Qt::AlignCenter); + mainLayout->addStretch(); + + connect(m_backButton, &InhibitButton::clicked, this, &UsersWithTheSameName::clicked); + connect(m_backButton, &InhibitButton::mouseEnter, this, [this] { + updateCurrentSelectedUser(true); + }); + connect(m_backButton, &InhibitButton::mouseLeave, this, [this] { + updateCurrentSelectedUser(false); + }); +} + +void UsersWithTheSameName::clearUserPanelList() +{ + // 释放之前创建的用户列表窗体 + for (auto widget : m_loginWidgets) { + widget->deleteLater(); + } + m_loginWidgets.clear(); +} + +bool UsersWithTheSameName::findUsers(const QString nativeUserName, const QString &doMainAccountDetail) +{ + auto createUserPanel = [this](const QString &avatar, const QString &fullName, const QString &name, const QString &type, const uint uid)-> UserPanel * { + UserPanel *widget = new UserPanel(m_centerWidget); + // 初始化用户信息 + widget->setAvatar(avatar); + widget->setName(name); + widget->setFullName(fullName); + widget->setDisplayName(fullName.isEmpty() ? name : fullName); + widget->setType(type); + widget->setUid(uid); + connect(widget, &UserPanel::requestAction, this, &UsersWithTheSameName::onUserClicked); + connect(widget, &UserPanel::mouseEnter, this, [this] { + updateCurrentSelectedUser(true); + }); + connect(widget, &UserPanel::mouseLeave, this, [this] { + updateCurrentSelectedUser(false); + }); + return widget; + }; + clearUserPanelList(); + std::shared_ptr nativeUser = m_model->findUserByName(nativeUserName); + const QJsonDocument &jsonDoc = QJsonDocument::fromJson(doMainAccountDetail.toUtf8()); + if (!jsonDoc.isObject()) { + qCWarning(DDE_SHELL) << "Invalid JSON data."; + if (nativeUser) { + Q_EMIT requestCheckAccount(nativeUser->name()); + } + clearUserPanelList(); + return false; + } + const QJsonObject &jsonObject = jsonDoc.object(); + QString fullName; + // 检查fullname字段是否存在,如果存在则使用,否则使用name字段的值 + if (jsonObject.contains("fullname")) { + fullName = jsonObject.value("fullname").toString(); + } else { + fullName = jsonObject.value("name").toString(); + } + const QString &name = jsonObject.value("name").toString(); + const uint uid = jsonObject.value("uid").toInt(); + + if (name == nativeUserName) { + qCWarning(DDE_SHELL) << "Domain user name is the same as the native user name"; + if (nativeUser) { + Q_EMIT requestCheckAccount(nativeUser->name()); + } + clearUserPanelList(); + return false; + } + + if (nativeUser) { + UserPanel *widget = createUserPanel(nativeUser->avatar(), nativeUser->fullName(), nativeUser->name(), tr("Local Account"), nativeUser->uid()); + m_loginWidgets.push_back(widget); + } + + // 检查本地是否已经创建过域账户 + std::shared_ptr domainUser = m_model->findUserByName(name); + UserPanel *widget = domainUser ? createUserPanel(domainUser->avatar(), domainUser->fullName(), domainUser->name(), tr("Domain Account"), domainUser->uid()) + : createUserPanel(":/img/default_avatar.svg", fullName, name, tr("Domain Account"), uid); + m_loginWidgets.push_back(widget); + + addUserPanel(m_loginWidgets); + return true; +} + +//创建用户窗体 +void UsersWithTheSameName::addUserPanel(QList &list) +{ + //多用户的情况按照其uid排序,升序排列,符合账户先后创建顺序 + std::sort(list.begin(), list.end(), [](UserPanel *w1, UserPanel *w2) { + return (w1->uid() < w2->uid()); + }); + for (int index = 0; index < list.size(); ++index) { + m_panelLayout->insertWidget(index, list[index]); + } + + m_centerWidget->setFixedSize(UserPanelWidth + 20, list.size() * (UserPanelHeight + UserPanelSpacing) - UserPanelSpacing); +} + +//点击用户 +void UsersWithTheSameName::onUserClicked() +{ + UserPanel *widget = static_cast(sender()); + if (!widget) return; + + m_currentSelectedUser = widget; + Q_EMIT clicked(); + Q_EMIT requestCheckAccount(widget->name()); +} + +/** + * @brief 切换下一个用户 + */ +void UsersWithTheSameName::switchNextUser() +{ + for (int i = 0; i < m_loginWidgets.size(); ++i) { + if (m_loginWidgets[i]->isSelected()) { + m_loginWidgets[i]->setSelected(false); + if (i + 1 < (m_loginWidgets.size())) { + m_currentSelectedUser = m_loginWidgets[i + 1]; + m_currentSelectedUser->setSelected(true); + + } else { + m_currentSelectedUser = nullptr; + m_backButton->setSelected(true); + } + break; + } else if (i == (m_loginWidgets.size() - 1)) { + m_currentSelectedUser = m_loginWidgets.first(); + m_currentSelectedUser->setSelected(true); + m_backButton->setSelected(false); + break; + } + } +} + +/** + * @brief 切换上一个用户 + */ +void UsersWithTheSameName::switchPreviousUser() +{ + for (int i = 0; i < m_loginWidgets.size(); ++i) { + if (m_loginWidgets[i]->isSelected()) { + m_loginWidgets[i]->setSelected(false); + if (i - 1 >= 0) { + m_currentSelectedUser = m_loginWidgets[i - 1]; + m_currentSelectedUser->setSelected(true); + m_backButton->setSelected(false); + } else { + m_currentSelectedUser = nullptr; + m_backButton->setSelected(true); + } + break; + } else if (i == (m_loginWidgets.size() - 1)) { + if (m_backButton->isSelected()) { + m_currentSelectedUser = m_loginWidgets.last(); + m_currentSelectedUser->setSelected(true); + m_backButton->setSelected(false); + break; + } + m_currentSelectedUser = nullptr; + m_backButton->setSelected(true); + break; + } + } +} + +void UsersWithTheSameName::hideEvent(QHideEvent *event) +{ + return QWidget::hideEvent(event); +} + +void UsersWithTheSameName::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Up: + switchPreviousUser(); + break; + case Qt::Key_Down: + switchNextUser(); + break; + case Qt::Key_Return: + case Qt::Key_Enter: + if (m_backButton->isSelected()) { + Q_EMIT clicked(); + break; + } + for (auto it = m_loginWidgets.constBegin(); it != m_loginWidgets.constEnd(); ++it) { + if ((*it)->isSelected()) { + Q_EMIT(*it)->requestAction(); + break; + } + } + break; + case Qt::Key_Escape: + Q_EMIT clicked(); + Q_EMIT requestCheckAccount(m_model->currentUser()->name()); + break; + default: + break; + } + return QWidget::keyPressEvent(event); +} + +void UsersWithTheSameName::updateCurrentSelectedUser(bool isMouseEner) +{ + if (!isMouseEner || m_backButton->underMouse()) { + if (m_currentSelectedUser != nullptr) + m_currentSelectedUser->setSelected(false); + } else { + for (int i = 0; i < m_loginWidgets.size(); ++i) { + if (m_loginWidgets[i]->underMouse() && !m_loginWidgets[i]->isSelected()) { + if (m_currentSelectedUser) + m_currentSelectedUser->setSelected(false); + m_currentSelectedUser = m_loginWidgets[i]; + m_currentSelectedUser->setSelected(true); + m_backButton->setSelected(false); + break; + } + } + } + +} + diff --git a/src/session-widgets/userswiththesamename.h b/src/session-widgets/userswiththesamename.h new file mode 100644 index 00000000..a5f66294 --- /dev/null +++ b/src/session-widgets/userswiththesamename.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef USERSWITHTHESAMENAME_H +#define USERSWITHTHESAMENAME_H + +#include "inhibitbutton.h" + +#include + +class UserPanel; +class SessionBaseModel; +class QVBoxLayout; + +class UsersWithTheSameName : public QWidget +{ + Q_OBJECT +public: + explicit UsersWithTheSameName(SessionBaseModel *model, QWidget *parent = nullptr); + bool findUsers(const QString nativeUserName, const QString &doMainAccountDetail); + +signals: + void requestCheckAccount(const QString &account, bool switchUser = true); + void clicked(); + +protected: + void hideEvent(QHideEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + +private: + void initUI(); + void addUserPanel(QList &list); + void onUserClicked(); + void switchNextUser(); + void switchPreviousUser(); + void updateCurrentSelectedUser(bool isMouseEner); + void clearUserPanelList(); + +private: + QVBoxLayout *m_panelLayout; + QList m_loginWidgets; + QPointer m_currentSelectedUser; + SessionBaseModel *m_model; + QWidget *m_centerWidget; + InhibitButton *m_backButton; +}; + +#endif // USERSWITHTHESAMENAME_H diff --git a/src/widgets/abstractfullbackgroundinterface.h b/src/widgets/abstractfullbackgroundinterface.h new file mode 100644 index 00000000..a0357f14 --- /dev/null +++ b/src/widgets/abstractfullbackgroundinterface.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ABSTRACTFULLBACKGROUND_H +#define ABSTRACTFULLBACKGROUND_H + +#include +#include + +class AbstractFullBackgroundInterface +{ +public: + virtual void setScreen(QPointer screen, bool isVisible = true) = 0; +}; + +#endif // ABSTRACTFULLBACKGROUND_H diff --git a/src/widgets/actionwidget.cpp b/src/widgets/actionwidget.cpp new file mode 100644 index 00000000..84ca439d --- /dev/null +++ b/src/widgets/actionwidget.cpp @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "actionwidget.h" + +#include + +#include +#include +#include + +ActionWidget::ActionWidget(QWidget *parent) + : QWidget(parent) + , m_state(Leave) + , m_radius(8) +{ +} + +void ActionWidget::setState(const State state) +{ + m_state = state; + update(); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void ActionWidget::enterEvent(QEnterEvent *event) +#else +void ActionWidget::enterEvent(QEvent *event) +#endif +{ + Q_EMIT mouseEnter(); + m_state = Enter; + update(); + + QWidget::enterEvent(event); +} + +void ActionWidget::leaveEvent(QEvent *event) +{ + Q_EMIT mouseLeave(); + m_state = Leave; + update(); + + QWidget::leaveEvent(event); +} + +void ActionWidget::mouseReleaseEvent(QMouseEvent *event) +{ + m_state = Release; + Q_EMIT requestAction(); + update(); + + QWidget::mouseReleaseEvent(event); +} + +void ActionWidget::mousePressEvent(QMouseEvent *event) +{ + m_state = Press; + update(); + + QWidget::mousePressEvent(event); +} + +void ActionWidget::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + m_state = Press; + } + update(); + + QWidget::keyReleaseEvent(event); +} + +void ActionWidget::keyReleaseEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + emit requestAction(); + m_state = Release; + } + update(); + + QWidget::keyReleaseEvent(event); +} + +void ActionWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + painter.setPen(Qt::NoPen); + painter.setRenderHint(QPainter::Antialiasing, true); + + switch (m_state) { + case Enter: + painter.setBrush(QColor(255, 255, 255, 0.3 * 255)); + break; + case Leave: + painter.setBrush(QColor(255, 255, 255, 0.1 * 255)); + break; + case Release: + painter.setBrush(QColor(255, 255, 255, 0.3 * 255)); + break; + case Press: + painter.setBrush(QColor(255, 255, 255, 0.1 * 255)); + break; + } + painter.drawRoundedRect(rect(), m_radius, m_radius); + + QWidget::paintEvent(event); +} diff --git a/src/widgets/actionwidget.h b/src/widgets/actionwidget.h new file mode 100644 index 00000000..61b0c0c3 --- /dev/null +++ b/src/widgets/actionwidget.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ACTIONWIDGET_H +#define ACTIONWIDGET_H + +#include +#include + +class ActionWidget : public QWidget +{ + Q_OBJECT +public: + enum State { + Enter, + Leave, + Press, + Release + }; + + explicit ActionWidget(QWidget *parent = nullptr); + + inline State state() { return m_state; } + void setState(const State state); + + void setRadius(int radius) { m_radius = radius; } + +signals: + void requestAction(); + void mouseEnter(); + void mouseLeave(); + +protected: +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *e) override; +#else + void enterEvent(QEvent *e) override; +#endif + void leaveEvent(QEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void paintEvent(QPaintEvent *event) override; + + State m_state; + int m_radius; +}; + +#endif // ACTIONWIDGET_H diff --git a/src/widgets/black_widget.cpp b/src/widgets/black_widget.cpp index d06ff447..f22dbc38 100644 --- a/src/widgets/black_widget.cpp +++ b/src/widgets/black_widget.cpp @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2020 ~ 2022 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "black_widget.h" #include diff --git a/src/widgets/black_widget.h b/src/widgets/black_widget.h index 8d229ca3..8d175ab7 100644 --- a/src/widgets/black_widget.h +++ b/src/widgets/black_widget.h @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2020 ~ 2022 Uniontech Software Technology Co.,Ltd. - * - * Author: Zhang Qipeng - * - * Maintainer: Zhang Qipeng - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #pragma once #include diff --git a/src/widgets/centertopwidget.cpp b/src/widgets/centertopwidget.cpp new file mode 100644 index 00000000..7dfd4522 --- /dev/null +++ b/src/widgets/centertopwidget.cpp @@ -0,0 +1,282 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "centertopwidget.h" +#include "public_func.h" +#include "dconfig_helper.h" +#include "constants.h" + +#include +#include +#include + +DCORE_USE_NAMESPACE +using namespace DDESESSIONCC; + +const int TOP_TIP_MAX_LENGTH = 60; +const int TOP_TIP_SPACING = 10; + +#ifdef ENABLE_DSS_SNIPE +static const QString localeNameKey = "localeName"; +static const QString shortDateFormatKey = "shortDateFormat"; +static const QString shortTimeFormatKey = "shortTimeFormat"; +#endif // ENABLE_DSS_SNIPE + +CenterTopWidget::CenterTopWidget(QWidget *parent) + : QWidget(parent) + , m_currentUser(nullptr) + , m_timeWidget(new TimeWidget(this)) + , m_topTip(new QLabel(this)) + , m_topTipSpacer(new QSpacerItem(0, TOP_TIP_SPACING)) +{ + initUi(); +} + +void CenterTopWidget::initUi() +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + m_timeWidget->setAccessibleName("TimeWidget"); + // 处理时间制跳转策略,获取到时间制再显示时间窗口 + m_timeWidget->setVisible(false); + layout->addWidget(m_timeWidget, 1); + // 顶部提示语,一般用于定制项目,主线默认不展示 + m_topTip->setAlignment(Qt::AlignCenter); + QPalette palette = m_topTip->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + m_topTip->setPalette(palette); + // 设置字体大小 + bool ok; + int fontSize = DConfigHelper::instance()->getConfig(TOP_TIP_TEXT_FONT, 5).toInt(&ok); + if (!ok || fontSize < 0 || fontSize > 9) fontSize = DFontSizeManager::T6; + DFontSizeManager::instance()->bind(m_topTip, static_cast(fontSize)); + + layout->addSpacerItem(m_topTipSpacer); + layout->addWidget(m_topTip); + const bool showTopTip = DConfigHelper::instance()->getConfig(SHOW_TOP_TIP, false).toBool(); + m_topTipSpacer->changeSize(0, showTopTip ? TOP_TIP_SPACING : 0); + m_topTip->setVisible(showTopTip); + setTopTipText(DConfigHelper::instance()->getConfig(TOP_TIP_TEXT, "").toString()); + + DConfigHelper::instance()->bind(this, SHOW_TOP_TIP, &CenterTopWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, TOP_TIP_TEXT, &CenterTopWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, TOP_TIP_TEXT_FONT, &CenterTopWidget::onDConfigPropertyChanged); +} + +void CenterTopWidget::setCurrentUser(User *user) +{ + if (!user || m_currentUser.data() == user) { + return; + } + +#ifdef ENABLE_DSS_SNIPE + updateRegionFormatConnection(user); +#endif // ENABLE_DSS_SNIPE + m_currentUser = QPointer(user); + if (!m_currentUser.isNull()) { + for (auto connect : m_currentUserConnects) { + m_currentUser->disconnect(connect); + } + } + +#ifdef ENABLE_DSS_SNIPE + m_timeWidget->updateLocale(QLocale(getUserLocale(user))); +#else + auto locale = qApp->applicationName() == "dde-lock" ? QLocale::system().name() : user->locale(); + m_timeWidget->updateLocale(QLocale(locale)); +#endif // ENABLE_DSS_SNIPE + m_timeWidget->set24HourFormat(user->isUse24HourFormat()); + m_timeWidget->setWeekdayFormatType(user->weekdayFormat()); + m_timeWidget->setShortDateFormat(user->shortDateFormat()); + m_timeWidget->setShortTimeFormat(user->shortTimeFormat()); + + m_currentUserConnects << connect(user, &User::use24HourFormatChanged, this, &CenterTopWidget::updateTimeFormat, Qt::UniqueConnection) + << connect(user, &User::weekdayFormatChanged, m_timeWidget, &TimeWidget::setWeekdayFormatType) + << connect(user, &User::shortDateFormatChanged, m_timeWidget, &TimeWidget::setShortDateFormat) + << connect(user, &User::shortTimeFormatChanged, m_timeWidget, &TimeWidget::setShortTimeFormat); + + QTimer::singleShot(0, this, [this, user] { + updateTimeFormat(user->isUse24HourFormat()); + }); + +#ifdef ENABLE_DSS_SNIPE + updateUserDateTimeFormat(); +#endif // ENABLE_DSS_SNIPE +} + + +void CenterTopWidget::updateTimeFormat(bool use24) +{ + if (!m_currentUser.isNull()) { +#ifdef ENABLE_DSS_SNIPE + m_timeWidget->updateLocale(QLocale(getUserLocale(m_currentUser))); +#else + auto locale = qApp->applicationName() == "dde-lock" ? QLocale::system().name() : m_currentUser->locale(); + m_timeWidget->updateLocale(QLocale(locale)); +#endif // ENABLE_DSS_SNIPE + m_timeWidget->set24HourFormat(use24); + m_timeWidget->setVisible(true); + } +} + +void CenterTopWidget::setTopTipText(const QString &text) +{ + QString firstLine = text.split("\n").first(); + if (firstLine.length() > TOP_TIP_MAX_LENGTH) { + // 居中省略号,理论上需要判断字体是否支持,考虑到这种场景非常少, + // 而且省略号处理只是锦上添花,可以忽略这个判断。 + QChar ellipsisChar(0x2026); + firstLine = firstLine.left(60) + QString(ellipsisChar); + } + m_tipText = firstLine; + updateTopTipWidget(); +} + +QSize CenterTopWidget::sizeHint() const +{ + const int heightHint = m_timeWidget->sizeHint().height() + m_topTip->fontMetrics().height() + TOP_TIP_SPACING; + + return QSize(QWidget::sizeHint().width(), heightHint); +} + +void CenterTopWidget::resizeEvent(QResizeEvent *event) +{ + updateTopTipWidget(); + QWidget::resizeEvent(event); +} + +void CenterTopWidget::updateTopTipWidget() +{ + QString firstLine = m_tipText; + const int maxWidth = topLevelWidget()->geometry().width() - 30; + if (m_topTip->fontMetrics().boundingRect(firstLine).width() > maxWidth) + firstLine = m_topTip->fontMetrics().elidedText(firstLine, Qt::ElideRight, maxWidth); + + m_topTip->setText(firstLine); +} + +void CenterTopWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == SHOW_TOP_TIP) { + const bool showTopTip = value.toBool(); + obj->m_topTipSpacer->changeSize(0, showTopTip ? TOP_TIP_SPACING : 0); + obj->m_topTip->setVisible(showTopTip); + } else if (key == TOP_TIP_TEXT) { + obj->setTopTipText(value.toString()); + } else if (key == TOP_TIP_TEXT_FONT) { + bool ok; + const int fontSize = value.toInt(&ok); + if (ok && fontSize > 0 && fontSize < 9) + DFontSizeManager::instance()->bind(obj->m_topTip, static_cast(fontSize)); + else + qCWarning(DDE_SHELL) << "Top tip text font format error, font size: " << fontSize; + } +} + +#ifdef ENABLE_DSS_SNIPE +void CenterTopWidget::onUserRegionFormatValueChanged(const QDBusMessage &dbusMessage) +{ + QList arguments = dbusMessage.arguments(); + if (1 != arguments.count()) + return; + + QString key = dbusMessage.arguments().at(0).toString(); + if (key == localeNameKey || key == shortTimeFormatKey || key == shortDateFormatKey) { + updateUserDateTimeFormat(); + } +} + +QString CenterTopWidget::getRegionFormatConfigPath(const User *user) const +{ + if (!user) + return QString(); + + QDBusInterface configInter("org.desktopspec.ConfigManager", "/", "org.desktopspec.ConfigManager", QDBusConnection::systemBus()); + if (!configInter.isValid()) { + qWarning("Can't acquire config manager. error:\"%s\"", + qPrintable(QDBusConnection::systemBus().lastError().message())); + return QString(); + } + QDBusReply dbusReply = configInter.call("acquireManagerV2", + (uint)user->uid(), + QString(QCoreApplication::applicationName()), + QString("org.deepin.region-format"), + QString("")); + if (configInter.lastError().isValid() ) { + qWarning("Call failed: %s", qPrintable(configInter.lastError().message())); + return QString(); + } + return dbusReply.value().path(); +} + +QString CenterTopWidget::getRegionFormatValue(const QString &userConfigDbusPath, const QString &key) const +{ + if (userConfigDbusPath.isEmpty()) + return QString(); + QDBusInterface managerInter("org.desktopspec.ConfigManager", userConfigDbusPath, "org.desktopspec.ConfigManager.Manager", QDBusConnection::systemBus()); + QDBusReply reply = managerInter.call("value", key); + if (managerInter.lastError().isValid() ) { + qWarning("Call failed: %s", qPrintable(managerInter.lastError().message())); + return QString(); + } + return reply.value().toString(); +} + +QString CenterTopWidget::getUserLocale(const User *user) const +{ + if (!user) + return QLocale::system().name(); + + if (qApp->applicationName() == "dde-lock") + return QLocale::system().name(); + + QString userConfigDbusPath = getRegionFormatConfigPath(user); + QString localeName = getRegionFormatValue(userConfigDbusPath, localeNameKey); + if (localeName.isEmpty()) { + localeName = user->locale(); + } + return localeName; +} + +void CenterTopWidget::updateRegionFormatConnection(const User *user) +{ + if (!user) { + return; + } + + // disconnect old user + if (m_currentUser) { + QString dbusPath = getRegionFormatConfigPath(m_currentUser); + if (dbusPath.isEmpty()) + return; + QDBusConnection::systemBus().disconnect("org.desktopspec.ConfigManager", dbusPath, "org.desktopspec.ConfigManager.Manager", + "valueChanged", "s", this, + SLOT(onUserRegionFormatValueChanged(const QDBusMessage&))); + } + + // connect new user + QString dbusPath = getRegionFormatConfigPath(user); + if (dbusPath.isEmpty()) + return; + + QDBusConnection::systemBus().connect("org.desktopspec.ConfigManager", dbusPath, "org.desktopspec.ConfigManager.Manager", + "valueChanged", "s", this, + SLOT(onUserRegionFormatValueChanged(const QDBusMessage&))); +} + +void CenterTopWidget::updateUserDateTimeFormat() +{ + QString userConfigDbusPath = getRegionFormatConfigPath(m_currentUser); + + QString localeName = qApp->applicationName() == "dde-lock" ? QLocale::system().name() : getRegionFormatValue(userConfigDbusPath, localeNameKey); + QString shortTimeFormat = getRegionFormatValue(userConfigDbusPath, shortTimeFormatKey); + QString shortDateFormat = getRegionFormatValue(userConfigDbusPath, shortDateFormatKey); + + m_timeWidget->updateLocale(localeName, shortTimeFormat, shortDateFormat); +} +#endif // ENABLE_DSS_SNIPE diff --git a/src/widgets/centertopwidget.h b/src/widgets/centertopwidget.h new file mode 100644 index 00000000..d114717d --- /dev/null +++ b/src/widgets/centertopwidget.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef CENTERTOPWIDGET_H +#define CENTERTOPWIDGET_H + +#include "userinfo.h" +#include "timewidget.h" + +#include +#include +#include +#include + +class CenterTopWidget : public QWidget +{ + Q_OBJECT +public: + explicit CenterTopWidget(QWidget *parent = nullptr); + void setCurrentUser(User *user); + QSize sizeHint() const override; + void resizeEvent(QResizeEvent *event) override; + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject* objPtr); + +signals: + +public slots: + void updateTimeFormat(bool use24); + + +private: + void initUi(); + void setTopTipText(const QString &text); + void updateTopTipWidget(); + +#ifdef ENABLE_DSS_SNIPE +private slots: + void onUserRegionFormatValueChanged(const QDBusMessage &dbusMessage); + +private: + QString getRegionFormatConfigPath(const User *user) const; + QString getRegionFormatValue(const QString &userConfigDbusPath, const QString& key) const; + QString getUserLocale(const User *user) const; + void updateRegionFormatConnection(const User *user); + void updateUserDateTimeFormat(); +#endif // ENABLE_DSS_SNIPE + +private: + QPointer m_currentUser; + TimeWidget *m_timeWidget; + QLabel *m_topTip; + QString m_tipText; + QSpacerItem *m_topTipSpacer; + QList m_currentUserConnects; +}; + +#endif // CENTERTOPWIDGET_H diff --git a/src/widgets/controlwidget.cpp b/src/widgets/controlwidget.cpp index bbd69fea..8253d725 100644 --- a/src/widgets/controlwidget.cpp +++ b/src/widgets/controlwidget.cpp @@ -1,68 +1,59 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "controlwidget.h" #include "sessionbasemodel.h" #include "kblayoutlistview.h" - -#include "mediawidget.h" -#include "modules_loader.h" -#include "tray_module_interface.h" -#include "tipswidget.h" #include "public_func.h" +#include "plugin_manager.h" +#include "dconfig_helper.h" +#include "popupwindow.h" #include #include #include #include -#include +#include #include #include #include -#include #include #include +#include #define BUTTON_ICON_SIZE QSize(26,26) #define BUTTON_SIZE QSize(52,52) +const QString NetworkPlugin = "network-item-key"; + using namespace dss; DCORE_USE_NAMESPACE +DGUI_USE_NAMESPACE -bool FlotingButton::eventFilter(QObject *watch, QEvent *event) +bool FloatingButton::eventFilter(QObject *watch, QEvent *event) { if (watch == this) { + if (event->type() == QEvent::Hide) { + Q_EMIT buttonHide(); + return false; + } + QMouseEvent *e = static_cast(event); if (event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *e = static_cast(event); + m_State = underMouse() ? Hover : Normal; if (e->button() == Qt::RightButton) { Q_EMIT requestShowMenu(); } } else if (event->type() == QEvent::Enter) { + m_State = Hover; Q_EMIT requestShowTips(); - } else if (event->type() == QEvent::Leave || event->type() == QEvent::MouseButtonPress) { + } else if (event->type() == QEvent::Leave) { + m_State = Normal; + Q_EMIT requestHideTips(); + } else if (event->type() == QEvent::MouseButtonPress) { + if (e->button() == Qt::LeftButton) + m_State = Press; Q_EMIT requestHideTips(); } } @@ -70,25 +61,54 @@ bool FlotingButton::eventFilter(QObject *watch, QEvent *event) return false; } +void FloatingButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + DStylePainter p(this); + DStyleOptionButton opt; + initStyleOption(&opt); + switch (m_State) + { + case Hover: + p.setOpacity(1.0); + break; + case Press: + p.setOpacity(0.4); + break; + case Normal: + p.setOpacity(0.7); + break; + default: + break; + } + p.drawControl(DStyle::CE_IconButton, opt); +} + ControlWidget::ControlWidget(const SessionBaseModel *model, QWidget *parent) : QWidget(parent) , m_contextMenu(new QMenu(this)) - , m_tipsWidget(new TipsWidget(this)) - , m_arrowRectWidget(new DArrowRectangle(DArrowRectangle::ArrowBottom, this)) - , m_kbLayoutListView(nullptr) - , m_keyboardBtn(nullptr) + , m_tipsWidget(new PopupWindow(parent)) , m_onboardBtnVisible(true) - , m_dconfig(DConfig::create(getDefaultConfigFileName(), getDefaultConfigFileName(), QString(), this)) + , m_doGrabKeyboard(true) + , m_canShowMenu(true) { setModel(model); initUI(); initConnect(); } +ControlWidget::~ControlWidget() +{ + if (m_tipsWidget) { + m_tipsWidget->deleteLater(); + } +} + void ControlWidget::setModel(const SessionBaseModel *model) { m_model = model; setUser(model->currentUser()); + connect(m_model, &SessionBaseModel::onStatusChanged, this, &ControlWidget::updateModuleVisible); } void ControlWidget::setUser(std::shared_ptr user) @@ -111,41 +131,39 @@ void ControlWidget::initKeyboardLayoutList() m_kbLayoutListView = new KBLayoutListView(language, this); m_kbLayoutListView->setAccessibleName(QStringLiteral("KbLayoutlistview")); m_kbLayoutListView->initData(m_curUser->keyboardLayoutList()); - m_kbLayoutListView->setMinimumWidth(DDESESSIONCC::KEYBOARDLAYOUT_WIDTH); - m_kbLayoutListView->setMaximumSize(DDESESSIONCC::KEYBOARDLAYOUT_WIDTH, DDESESSIONCC::LAYOUTBUTTON_HEIGHT * 7); + m_kbLayoutListView->setMinimumWidth(DDESESSIONCC::KEYBOARD_LAYOUT_WIDTH); + m_kbLayoutListView->setMaximumSize(DDESESSIONCC::KEYBOARD_LAYOUT_WIDTH, DDESESSIONCC::LAYOUT_BUTTON_HEIGHT * 7); m_kbLayoutListView->setFocusPolicy(Qt::NoFocus); + m_kbLayoutListView->setVisible(false); const QStringList languageList = language.split(";"); if (!languageList.isEmpty()) - static_cast(m_keyboardBtn)->setText(languageList.at(0)); - - // 无特效模式时,让窗口圆角 - m_arrowRectWidget->setProperty("_d_radius_force", true); - m_arrowRectWidget->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::WindowStaysOnTopHint); - m_arrowRectWidget->setMargin(0); - m_arrowRectWidget->setShadowBlurRadius(20); - m_arrowRectWidget->setRadius(6); - m_arrowRectWidget->setShadowYOffset(2); - m_arrowRectWidget->setShadowXOffset(0); - m_arrowRectWidget->setArrowWidth(18); - m_arrowRectWidget->setArrowHeight(10); - m_arrowRectWidget->setMinimumWidth(DDESESSIONCC::KEYBOARDLAYOUT_WIDTH); - m_arrowRectWidget->setMaximumSize(DDESESSIONCC::KEYBOARDLAYOUT_WIDTH, DDESESSIONCC::LAYOUTBUTTON_HEIGHT * 7); - m_arrowRectWidget->setFocusPolicy(Qt::NoFocus); - - QPalette pal = m_arrowRectWidget->palette(); - pal.setColor(DPalette::Inactive, DPalette::Base, QColor(235, 235, 235, int(0.05 * 255))); - setPalette(pal); - - m_arrowRectWidget->setContent(m_kbLayoutListView); + static_cast(m_keyboardBtn)->setText(languageList.at(0).toUpper()); + connect(m_kbLayoutListView, &KBLayoutListView::itemClicked, this, &ControlWidget::onItemClicked); - connect(m_kbLayoutListView, &KBLayoutListView::sizeChange, this, &ControlWidget::resizeArrowWidget); +} + +void ControlWidget::updatePluginVisible(const QString module, bool state) +{ + qCInfo(DDE_SHELL) << "Update plugin visible, state: " << state; + for (auto key : m_modules.keys()) { + if (key && key->objectName() == module) { + m_modules.value(key)->setVisible(state); + m_modulesVisible.insert(module, state); + + if (m_model->currentModeState() != SessionBaseModel::ModeStatus::PasswordMode) + m_modules.value(key)->setVisible(false); + + return; + } + } } void ControlWidget::setVirtualKBVisible(bool visible) { m_onboardBtnVisible = visible; - m_virtualKBBtn->setVisible(visible && !m_dconfig->value("hideOnboard", false).toBool()); + const bool hideOnboard = DConfigHelper::instance()->getConfig("hideOnboard", false).toBool(); + m_virtualKBBtn->setVisible(visible && !hideOnboard); } void ControlWidget::initUI() @@ -155,14 +173,14 @@ void ControlWidget::initUI() m_mainLayout->setSpacing(26); m_mainLayout->setAlignment(Qt::AlignRight | Qt::AlignBottom); - m_sessionBtn = new DFloatingButton(this); + m_sessionBtn = new FloatingButton(this); m_sessionBtn->setIconSize(BUTTON_ICON_SIZE); m_sessionBtn->setFixedSize(BUTTON_SIZE); m_sessionBtn->setAutoExclusive(true); m_sessionBtn->setBackgroundRole(DPalette::Button); m_sessionBtn->hide(); - m_keyboardBtn = new DFloatingButton(this); + m_keyboardBtn = new FloatingButton(this); m_keyboardBtn->setAccessibleName("KeyboardLayoutBtn"); m_keyboardBtn->setFixedSize(BUTTON_SIZE); m_keyboardBtn->setAutoExclusive(true); @@ -175,11 +193,12 @@ void ControlWidget::initUI() QPalette pal = m_keyboardBtn->palette(); pal.setColor(QPalette::Window, QColor(Qt::red)); pal.setColor(QPalette::HighlightedText, QColor(Qt::white)); + pal.setColor(QPalette::Highlight, Qt::white); m_keyboardBtn->setPalette(pal); - m_virtualKBBtn = new DFloatingButton(this); + m_virtualKBBtn = new FloatingButton(this); m_virtualKBBtn->setAccessibleName("VirtualKeyboardBtn"); - m_virtualKBBtn->setIcon(QIcon::fromTheme(":/img/screen_keyboard_normal.svg")); + m_virtualKBBtn->setIcon(QIcon::fromTheme(":/img/screen_keyboard_hover.svg")); m_virtualKBBtn->hide(); m_virtualKBBtn->setIconSize(BUTTON_ICON_SIZE); m_virtualKBBtn->setFixedSize(BUTTON_SIZE); @@ -187,18 +206,18 @@ void ControlWidget::initUI() m_virtualKBBtn->setBackgroundRole(DPalette::Button); m_virtualKBBtn->installEventFilter(this); - m_switchUserBtn = new DFloatingButton(this); + m_switchUserBtn = new FloatingButton(this); m_switchUserBtn->setAccessibleName("SwitchUserBtn"); - m_switchUserBtn->setIcon(QIcon::fromTheme(":/img/bottom_actions/userswitch_normal.svg")); + m_switchUserBtn->setIcon(QIcon::fromTheme(":/img/bottom_actions/userswitch_hover.svg")); m_switchUserBtn->setIconSize(BUTTON_ICON_SIZE); m_switchUserBtn->setFixedSize(BUTTON_SIZE); m_switchUserBtn->setAutoExclusive(true); m_switchUserBtn->setBackgroundRole(DPalette::Button); m_switchUserBtn->installEventFilter(this); - m_powerBtn = new DFloatingButton(this); + m_powerBtn = new FloatingButton(this); m_powerBtn->setAccessibleName("PowerBtn"); - m_powerBtn->setIcon(QIcon(":/img/bottom_actions/shutdown_normal.svg")); + m_powerBtn->setIcon(QIcon(":/img/bottom_actions/shutdown_hover.svg")); m_powerBtn->setIconSize(BUTTON_ICON_SIZE); m_powerBtn->setFixedSize(BUTTON_SIZE); m_powerBtn->setAutoExclusive(true); @@ -220,67 +239,106 @@ void ControlWidget::initUI() m_mainLayout->addWidget(m_switchUserBtn); m_mainLayout->addWidget(m_powerBtn); - QHash modules = module::ModulesLoader::instance().moduleList(); - for (module::BaseModuleInterface *module : modules.values()) { - addModule(module); - } - updateLayout(); // 初始化键盘布局列表 initKeyboardLayoutList(); + + DConfigHelper::instance()->bind(this, "hideOnboard", &ControlWidget::onDConfigPropertyChanged); } void ControlWidget::initConnect() { - connect(&module::ModulesLoader::instance(), &module::ModulesLoader::moduleFound, this, &ControlWidget::addModule); connect(m_sessionBtn, &DFloatingButton::clicked, this, &ControlWidget::requestSwitchSession); connect(m_switchUserBtn, &DFloatingButton::clicked, this, &ControlWidget::requestSwitchUser); connect(m_powerBtn, &DFloatingButton::clicked, this, &ControlWidget::requestShutdown); connect(m_virtualKBBtn, &DFloatingButton::clicked, this, &ControlWidget::requestSwitchVirtualKB); connect(m_keyboardBtn, &DFloatingButton::clicked, this, &ControlWidget::setKBLayoutVisible); connect(m_model, &SessionBaseModel::currentUserChanged, this, &ControlWidget::setUser); - connect(m_dconfig, &DConfig::valueChanged, this, [this] (const QString &key) { - if (m_virtualKBBtn && key == "hideOnboard") { - m_virtualKBBtn->setVisible(m_onboardBtnVisible && !m_dconfig->value("hideOnboard", false).toBool()); - } + connect(m_model, &SessionBaseModel::hidePluginMenu, m_contextMenu, [this] { + m_contextMenu->close(); + // 重置密码弹窗弹出的时候不重新抓取键盘,否则会导致重置密码弹窗无法抓取键盘 + m_doGrabKeyboard = false; }); } -void ControlWidget::addModule(module::BaseModuleInterface *module) +QString ControlWidget::messageCallback(const QString &message, void *app_data) { - if (module && module->type() != module::BaseModuleInterface::TrayType) - return; + if (!app_data && static_cast(app_data)) { + qCWarning(DDE_SHELL) << "Appdata is null, app data: " << app_data; + return QString(); + } + QJsonObject retObj; + QJsonParseError jsonParseError; + const QJsonDocument messageDoc = QJsonDocument::fromJson(message.toLatin1(), &jsonParseError); + if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { + retObj["Code"] = "-1"; + retObj["Message"] = "Failed to analysis message info from plugin!"; + qCWarning(DDE_SHELL) << "Failed to analysis message info from plugin!: " << message; + return toJson(retObj); + } + QJsonObject messageObj = messageDoc.object(); + + QString cmd = messageObj.value("Cmd").toString(); + const QString pluginKey = messageObj.value("PluginKey").toString(); + if (cmd == "ShowContent") { + emit static_cast(app_data)->requestShowModule(pluginKey, true); + } else if (cmd == "PluginVisible") { + static_cast(app_data)->updatePluginVisible(pluginKey, messageObj.value("Visible").toBool()); + } - module::TrayModuleInterface *trayModule = dynamic_cast(module); - if (!trayModule) - return; + return message; +} + +QWidget *ControlWidget::getTray(const QString &name) +{ + for (auto key : m_modules.keys()) { + if (key && key->objectName() == name) { + return m_modules.value(key); + } + } + + return nullptr; +} +void ControlWidget::addModule(TrayPlugin *trayModule) +{ trayModule->init(); - FlotingButton *button = new FlotingButton(this); + FloatingButton *button = new FloatingButton(this); button->setIconSize(QSize(26, 26)); button->setFixedSize(QSize(52, 52)); button->setAutoExclusive(true); button->setBackgroundRole(DPalette::Button); - if (QWidget *trayWidget = trayModule->itemWidget()) { - trayWidget->setParent(this); - QHBoxLayout *layout = new QHBoxLayout(this); + QWidget *trayWidget = trayModule->itemWidget(); + if (trayWidget) { + trayWidget->setParent(button); + QHBoxLayout *layout = new QHBoxLayout(button); layout->setSpacing(0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + layout->setContentsMargins(0, 0, 0, 0); +#else layout->setMargin(0); +#endif layout->addWidget(trayWidget); - - button->setLayout(layout); + button->setVisible(trayWidget->isVisible()); + trayWidget->setObjectName(trayModule->key()); } else { button->setIcon(QIcon(trayModule->icon())); } - m_modules.insert(trayModule->key(), button); + m_modules.insert(trayWidget, button); + + trayModule->setAppData(this); + trayModule->setMessageCallback(&ControlWidget::messageCallback); + // button的顺序与layout插入顺序保持一直 m_btnList.insert(1, button); - connect(button, &FlotingButton::requestShowMenu, this, [ = ] { + connect(button, &FloatingButton::requestShowMenu, this, [this, trayModule] { + if (!m_canShowMenu) + return; const QString menuJson = trayModule->itemContextMenu(); if (menuJson.isEmpty()) return; @@ -302,45 +360,60 @@ void ControlWidget::addModule(module::BaseModuleInterface *module) action->setEnabled(itemObj.value("isActive").toBool()); m_contextMenu->addAction(action); } - + m_doGrabKeyboard = true; QAction *action = m_contextMenu->exec(QCursor::pos()); if (action) trayModule->invokedMenuItem(action->data().toString(), true); + + // 右键菜单隐藏后需要重新grab键盘,否则会导致快捷键重新生效 + if (!m_model->isUseWayland() && m_doGrabKeyboard) { + QWindow *winHandle = topLevelWidget()->windowHandle(); + if (!winHandle || !winHandle->setKeyboardGrabEnabled(true)) { + qCWarning(DDE_SHELL) << "Grab keyboard failed"; + } + } }); - connect(button, &FlotingButton::requestShowTips, this, [ = ] { - if (trayModule->itemTipsWidget()) { + connect(button, &FloatingButton::requestShowTips, this, [=] { + if (trayModule->itemTipsWidget() && !trayModule->content()->isVisible() && topLevelWidget()) { m_tipsWidget->setContent(trayModule->itemTipsWidget()); - m_tipsWidget->show(mapToGlobal(button->pos()).x() + button->width() / 2,mapToGlobal(button->pos()).y()); + // 因为密码框需要一直获取焦点,会导致TipsWidget在间隙时间内的Visible变为false + // DArrowRectangle::show中当Visible为false时会activateWindow,抢占密码框焦点 + // 所以这里手动设置visible为true + int x = mapTo(topLevelWidget(), button->pos()).x() + button->width() / 2; + int y = mapTo(topLevelWidget(), button->pos()).y(); + m_tipsWidget->move(x, y); + m_tipsWidget->setVisible(true); + m_tipsWidget->show(QPoint(x, y)); } }); - connect(button, &FlotingButton::requestHideTips, this, [ = ] { + connect(button, &FloatingButton::requestHideTips, this, [=] { if (m_tipsWidget->getContent()) m_tipsWidget->getContent()->setVisible(false); m_tipsWidget->hide(); + update(); }); - connect(button, &DFloatingButton::clicked, this, [this, trayModule] { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + connect(button, &FloatingButton::clicked, this, [this, trayModule] { + emit requestShowModule(trayModule->key()); + }); +#else + connect(button, &FloatingButton::clicked, this, [this, trayModule] { emit requestShowModule(trayModule->key()); }, Qt::UniqueConnection); - - +#endif updateLayout(); } -void ControlWidget::removeModule(module::BaseModuleInterface *module) +void ControlWidget::removeModule(TrayPlugin *trayModule) { - if (module->type() != module::BaseModuleInterface::TrayType) - return; - - module::TrayModuleInterface *trayModule = dynamic_cast(module); - - QMap::const_iterator i = m_modules.constBegin(); + auto i = m_modules.constBegin(); while (i != m_modules.constEnd()) { - if (i.key() == trayModule->key()) { + if (i.key() && i.key()->objectName() == trayModule->key()) { m_modules.remove(i.key()); - m_btnList.removeAll(dynamic_cast(i.value())); + m_btnList.removeAll(dynamic_cast(i.value().data())); updateLayout(); break; } @@ -455,7 +528,7 @@ void ControlWidget::setSessionSwitchEnable(const bool visible) void ControlWidget::chooseToSession(const QString &session) { if (m_sessionBtn && m_sessionTip) { - qDebug() << "chosen session: " << session; + qCDebug(DDE_SHELL) << "Chosen session: " << session; if (session.isEmpty()) return; @@ -539,10 +612,7 @@ void ControlWidget::setKBLayoutVisible() if (!layoutButton) return; - // 算上三角形的高度 - QPoint pos = mapToGlobal(layoutButton->pos()) - QPoint((m_kbLayoutListView->width() - layoutButton->width())/2, m_kbLayoutListView->height() + 10); - m_arrowRectWidget->setGeometry(QRect(pos, m_kbLayoutListView->size() + QSize(0, 10))); - m_arrowRectWidget->setVisible(!m_arrowRectWidget->isVisible()); + Q_EMIT requestShowTrayModule(layoutButton, m_kbLayoutListView); } void ControlWidget::setKeyboardType(const QString &str) @@ -553,7 +623,7 @@ void ControlWidget::setKeyboardType(const QString &str) if (currentText.contains("/")) currentText = currentText.split("/").last(); - static_cast(m_keyboardBtn)->setText(currentText); + static_cast(m_keyboardBtn)->setText(currentText.toUpper()); // 更新键盘布局列表 m_kbLayoutListView->updateList(str); @@ -579,15 +649,24 @@ void ControlWidget::onItemClicked(const QString &str) if (currentText.contains("/")) currentText = currentText.split("/").last(); - static_cast(m_keyboardBtn)->setText(currentText); - m_arrowRectWidget->hide(); + static_cast(m_keyboardBtn)->setText(currentText.toUpper()); + // hide keyboard layout popup + Q_EMIT requestShowTrayModule(m_keyboardBtn, m_kbLayoutListView); m_curUser->setKeyboardLayout(str); } -void ControlWidget::resizeArrowWidget() +void ControlWidget::updateModuleVisible() { - if (m_arrowRectWidget) - m_arrowRectWidget->setFixedSize(m_kbLayoutListView->size() + QSize(0, 10)); + for (auto key : m_modules.keys()) { + if (key) { + const QString &module = key->objectName(); + bool visible = m_model->currentModeState() == SessionBaseModel::ModeStatus::PasswordMode; + if(m_modulesVisible.contains(module)){ + visible &= m_modulesVisible.value(module); + } + m_modules.value(key)->setVisible(visible); + } + } } bool ControlWidget::eventFilter(QObject *watched, QEvent *event) @@ -606,12 +685,13 @@ bool ControlWidget::eventFilter(QObject *watched, QEvent *event) } } - DFloatingButton *btn = dynamic_cast(watched); - if (m_btnList.contains(btn)) { + DFloatingButton *btn = qobject_cast(watched); + if (btn && m_btnList.contains(btn)) { if (event->type() == QEvent::Enter) { m_index = m_btnList.indexOf(btn); } } + #else Q_UNUSED(watched); Q_UNUSED(event); @@ -631,11 +711,51 @@ void ControlWidget::keyReleaseEvent(QKeyEvent *event) case Qt::Key_Tab: auto it = std::find_if(m_btnList.begin(), m_btnList.end(), [](DFloatingButton *btn) { return btn->hasFocus(); }); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_index = it != m_btnList.end() ? m_btnList.indexOf(*it) : 0; +#else m_index = it != m_btnList.end() ? m_btnList.indexOf(it.i->t()) : 0; +#endif break; } } +void ControlWidget::showEvent(QShowEvent *event) +{ + // 对tray类型插件延时处理,避免阻塞主界面显示。 + QTimer::singleShot(500, this, [this]{ + auto initPlugins = [this] { + for (const auto &module : PluginManager::instance()->trayPlugins()) { + if (!module) + continue; + + addModule(module); + } + }; + static bool isInit = false; + if (!isInit) { + initPlugins(); + isInit = true; + connect(PluginManager::instance(), &PluginManager::trayPluginAdded, this, [this](TrayPlugin *module) { + if (!module) + return; + + addModule(module); + }); + } + + for (auto key : m_modules.keys()) { + auto value = m_modules.value(key); + if (!value) { + continue; + } + value->setVisible(key->isVisibleTo(this)); + } + }); + + QWidget::showEvent(event); +} + void ControlWidget::updateTapOrder() { // 找出所有按钮 @@ -652,3 +772,14 @@ void ControlWidget::updateTapOrder() setTabOrder(buttons[i], buttons[i + 1]); } } + +void ControlWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (obj->m_virtualKBBtn && key == "hideOnboard") { + obj->m_virtualKBBtn->setVisible(obj->m_onboardBtnVisible && !value.toBool()); + } +} diff --git a/src/widgets/controlwidget.h b/src/widgets/controlwidget.h index 84c50b32..2edb15c9 100644 --- a/src/widgets/controlwidget.h +++ b/src/widgets/controlwidget.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef CONTROLWIDGET_H #define CONTROLWIDGET_H @@ -29,9 +8,11 @@ #include #include #include "userinfo.h" +#include "tray_plugin.h" #include #include +#include #include #include @@ -49,10 +30,6 @@ DWIDGET_BEGIN_NAMESPACE class DArrowRectangle; DWIDGET_END_NAMESPACE -DCORE_BEGIN_NAMESPACE -class DConfig; -DCORE_END_NAMESPACE - class MediaWidget; class QHBoxLayout; class QPropertyAnimation; @@ -61,53 +38,67 @@ class QMenu; class SessionBaseModel; class KBLayoutListView; class TipsWidget; +class PopupWindow; const int BlurRadius = 15; const int BlurTransparency = 70; -class FlotingButton : public DFloatingButton +class FloatingButton : public DFloatingButton { Q_OBJECT public: - explicit FlotingButton(QWidget *parent = nullptr) + enum IconState { + Normal, + Hover, + Press + }; + explicit FloatingButton(QWidget *parent = nullptr) : DFloatingButton(parent) { installEventFilter(this); } - explicit FlotingButton(QStyle::StandardPixmap iconType = static_cast(-1), QWidget *parent = nullptr) + explicit FloatingButton(QStyle::StandardPixmap iconType = static_cast(-1), QWidget *parent = nullptr) : DFloatingButton(iconType, parent) { installEventFilter(this); } - explicit FlotingButton(DStyle::StandardPixmap iconType = static_cast(-1), QWidget *parent = nullptr) + explicit FloatingButton(DStyle::StandardPixmap iconType = static_cast(-1), QWidget *parent = nullptr) : DFloatingButton(iconType, parent) { installEventFilter(this); } - explicit FlotingButton(const QString &text, QWidget *parent = nullptr) + explicit FloatingButton(const QString &text, QWidget *parent = nullptr) : DFloatingButton(text, parent) { installEventFilter(this); } - FlotingButton(const QIcon& icon, const QString &text = QString(), QWidget *parent = nullptr) + FloatingButton(const QIcon& icon, const QString &text = QString(), QWidget *parent = nullptr) : DFloatingButton(icon, text, parent) { installEventFilter(this); } +private: + IconState m_State = Normal; + Q_SIGNALS: void requestShowMenu(); void requestShowTips(); void requestHideTips(); + void buttonHide(); protected: bool eventFilter(QObject *watch, QEvent *event) override; + void paintEvent(QPaintEvent *event) override; }; class ControlWidget : public QWidget { Q_OBJECT public: explicit ControlWidget(const SessionBaseModel *model, QWidget *parent = nullptr); + ~ControlWidget() override; void setModel(const SessionBaseModel *model); void setUser(std::shared_ptr user); void initKeyboardLayoutList(); + QWidget *getTray(const QString &name); + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); signals: void requestSwitchUser(); @@ -115,11 +106,13 @@ class ControlWidget : public QWidget void requestSwitchSession(); void requestSwitchVirtualKB(); void requestKeyboardLayout(const QPoint &pos); - void requestShowModule(const QString &name); + void requestShowModule(const QString &name, const bool callShowForce = false); + void requestShowTrayModule(QWidget *trayWidget, QWidget *contentWidget, const bool callShowForce = false); + void notifyKeyboardLayoutHidden(); public slots: - void addModule(dss::module::BaseModuleInterface *module); - void removeModule(dss::module::BaseModuleInterface *module); + void addModule(TrayPlugin *module); + void removeModule(TrayPlugin *module); void setVirtualKBVisible(bool visible); void setUserSwitchEnable(const bool visible); void setSessionSwitchEnable(const bool visible); @@ -130,11 +123,14 @@ public slots: void setKeyboardType(const QString& str); void setKeyboardList(const QStringList& str); void onItemClicked(const QString& str); - void resizeArrowWidget(); + void updateModuleVisible(); + void setCanShowMenu(bool state) { m_canShowMenu = state; } + void updatePluginVisible(const QString module, bool state); protected: bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; private: void initUI(); @@ -143,33 +139,36 @@ public slots: void hideTips(); void updateLayout(); void updateTapOrder(); + static QString messageCallback(const QString &message, void *app_data); private: int m_index = 0; QList m_btnList; QHBoxLayout *m_mainLayout = nullptr; - DFloatingButton *m_virtualKBBtn = nullptr; - DFloatingButton *m_switchUserBtn = nullptr; - DFloatingButton *m_powerBtn = nullptr; - DFloatingButton *m_sessionBtn = nullptr; + FloatingButton *m_virtualKBBtn = nullptr; + FloatingButton *m_switchUserBtn = nullptr; + FloatingButton *m_powerBtn = nullptr; + FloatingButton *m_sessionBtn = nullptr; QLabel *m_sessionTip = nullptr; QWidget *m_tipWidget = nullptr; #ifndef SHENWEI_PLATFORM QPropertyAnimation *m_tipsAni = nullptr; #endif - QMap m_modules; + QMap, QPointer> m_modules; + QMap m_modulesVisible; + QMenu *m_contextMenu; - TipsWidget *m_tipsWidget; + PopupWindow *m_tipsWidget = nullptr; const SessionBaseModel *m_model; - DArrowRectangle *m_arrowRectWidget; - KBLayoutListView *m_kbLayoutListView; // 键盘布局列表 - DFloatingButton *m_keyboardBtn; // 键盘布局按钮 + KBLayoutListView *m_kbLayoutListView = nullptr; // 键盘布局列表 + FloatingButton *m_keyboardBtn = nullptr; // 键盘布局按钮 std::shared_ptr m_curUser; QList m_connectionList; bool m_onboardBtnVisible; - DTK_CORE_NAMESPACE::DConfig *m_dconfig; + bool m_doGrabKeyboard; + bool m_canShowMenu; }; #endif // CONTROLWIDGET_H diff --git a/src/widgets/dlineeditex.cpp b/src/widgets/dlineeditex.cpp index f753dc67..94b821a4 100644 --- a/src/widgets/dlineeditex.cpp +++ b/src/widgets/dlineeditex.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "dlineeditex.h" @@ -27,6 +10,8 @@ #include #include #include +#include +#include LoadSlider::LoadSlider(QWidget *parent) : QWidget(parent) @@ -45,7 +30,7 @@ void LoadSlider::paintEvent(QPaintEvent *event) QLinearGradient grad(0, height() / 2, width(), height() / 2); grad.setColorAt(0.0, Qt::transparent); grad.setColorAt(1.0, m_loadSliderColor); - painter.fillRect(0, 1, width(), height() - 2, grad); + painter.fillRect(0, 0, width(), height() - 1, grad); QWidget::paintEvent(event); } @@ -54,6 +39,8 @@ DLineEditEx::DLineEditEx(QWidget *parent) : DLineEdit(parent) , m_loadSlider(new LoadSlider(this)) , m_animation(new QPropertyAnimation(m_loadSlider, "pos", m_loadSlider)) + , m_enableTableKeyEvent(false) + , m_secureInputEnabled(false) { setObjectName(QStringLiteral("DLineEditEx")); setAccessibleName(QStringLiteral("DLineEditEx")); @@ -94,6 +81,13 @@ void DLineEditEx::setPlaceholderTextFont(const QFont &font) const QString &text = lineEdit()->placeholderText(); QFont fontTmp = font; while (QFontMetrics(fontTmp).boundingRect(text).width() > width()) { + // 防止陷入死循环,setPointSize当参数为负数的时候设置不生效 + // TODO: font()获取问题,需要继续调查下为啥font为啥会出问题,但是这里也需要增加跳出死循环的条件 + qDebug() << "Password line edit placeholder text width : " << QFontMetrics(fontTmp).boundingRect(text).width() << " line edit width : " << width(); + if (fontTmp.pointSize() <= 1) { + qWarning() << "Password line edit font size" << font.pointSize() << fontTmp.pointSize(); + return; + } fontTmp.setPointSize(fontTmp.pointSize() - 1); } setFont(fontTmp); @@ -109,8 +103,10 @@ void DLineEditEx::startAnimation() } m_loadSlider->show(); m_loadSlider->resize(40, height()); - m_animation->setStartValue(QPoint(0 - 40, 0)); - m_animation->setEndValue(QPoint(width(), 0)); + // 动画块距离右侧的距离10px结束 + int endX = (width() - m_loadSlider->width() - 10) > 0 ? width() - m_loadSlider->width() - 10 : width(); + m_animation->setStartValue(QPoint(0, 0)); + m_animation->setEndValue(QPoint(endX, 0)); m_animation->start(); } @@ -126,6 +122,22 @@ void DLineEditEx::stopAnimation() m_animation->stop(); } +void DLineEditEx::setEnableTableKeyEvent(bool enable) +{ + if (m_enableTableKeyEvent == enable) + return; + + m_enableTableKeyEvent = enable; +} + +void DLineEditEx::setSecureInputEnabled(bool enable) +{ + if (m_secureInputEnabled == enable) + return; + + m_secureInputEnabled = enable; +} + /** * @brief 重写 QLineEdit paintEvent 函数,实现当文本设置居中后,holderText 仍然显示的需求 * @@ -144,7 +156,19 @@ void DLineEditEx::paintEvent(QPaintEvent *event) pa.setPen(col); QTextOption option; option.setAlignment(Qt::AlignCenter); - pa.drawText(lineEdit()->rect(), lineEdit()->placeholderText(), option); + option.setWrapMode(QTextOption::NoWrap); + // 使用 elidedText 确保文本过长时在右侧显示省略号,而不是换行 + QFontMetrics fm(pa.font()); + const QString &placeholderText = lineEdit()->placeholderText(); + QString elidedText = fm.elidedText(placeholderText, Qt::ElideRight, rect().width()); + pa.drawText(rect(), Qt::AlignCenter | Qt::TextSingleLine, elidedText); + + // 当文本被省略时,设置 tooltip 显示完整文本 + if (elidedText != placeholderText) { + setToolTip(placeholderText); + } else { + setToolTip(QString()); + } } QWidget::paintEvent(event); } @@ -155,6 +179,26 @@ bool DLineEditEx::eventFilter(QObject *watched, QEvent *event) if ((watched == this || watched == this->lineEdit()) && event->type() == QEvent::InputMethodQuery) { return true; + } else if ((watched == this || watched == this->lineEdit()) + && event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + + if (m_secureInputEnabled + && (keyEvent->matches(QKeySequence::Cut) + || keyEvent->matches(QKeySequence::Copy) + || keyEvent->matches(QKeySequence::Paste) + || keyEvent->matches(QKeySequence::Undo) + || keyEvent->matches(QKeySequence::Redo))) { + return true; + } + + if (m_enableTableKeyEvent + && keyEvent->key() == Qt::Key_Tab + && keyEvent->modifiers() == Qt::NoModifier + && !this->text().isEmpty()) { + emit this->returnPressed(); + return true; + } } return DLineEdit::eventFilter(watched, event); diff --git a/src/widgets/dlineeditex.h b/src/widgets/dlineeditex.h index 4c0af56d..a0e42faa 100644 --- a/src/widgets/dlineeditex.h +++ b/src/widgets/dlineeditex.h @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef DLINEEDITEX_H #define DLINEEDITEX_H @@ -35,7 +18,6 @@ class LoadSlider : public QWidget LoadSlider(QWidget *parent = nullptr); public: - QColor loadSliderColor() const; void setLoadSliderColor(const QColor &color); protected: @@ -54,6 +36,8 @@ class DLineEditEx : public DLineEdit public slots: void startAnimation(); void stopAnimation(); + void setEnableTableKeyEvent(bool enable); + void setSecureInputEnabled(bool enable); protected: void paintEvent(QPaintEvent *event) override; @@ -66,6 +50,8 @@ public slots: private: LoadSlider *m_loadSlider; QPropertyAnimation *m_animation; + bool m_enableTableKeyEvent; + bool m_secureInputEnabled; }; #endif // DLINEEDITEX_H diff --git a/src/widgets/fullscreenbackground.cpp b/src/widgets/fullscreenbackground.cpp index ebdd68a4..aebb9787 100644 --- a/src/widgets/fullscreenbackground.cpp +++ b/src/widgets/fullscreenbackground.cpp @@ -1,35 +1,17 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "fullscreenbackground.h" #include "black_widget.h" +#include "lockcontent.h" #include "public_func.h" #include "sessionbasemodel.h" +#include "dconfig_helper.h" #include +#include #include #include @@ -39,6 +21,15 @@ #include #include +#ifndef ENABLE_DSS_SNIPE +#include +#else +#include +#endif +#include + +#include "dbusconstant.h" + Q_LOGGING_CATEGORY(DDE_SS, "dss.active") DGUI_USE_NAMESPACE @@ -46,235 +37,286 @@ DGUI_USE_NAMESPACE const int PIXMAP_TYPE_BACKGROUND = 0; const int PIXMAP_TYPE_BLUR_BACKGROUND = 1; -QString FullscreenBackground::backgroundPath; -QString FullscreenBackground::blurBackgroundPath; +QString FullScreenBackground::originBackgroundPath; +QString FullScreenBackground::blurBackgroundPath; -QList> FullscreenBackground::backgroundCacheList; -QList> FullscreenBackground::blurBackgroundCacheList; -QList FullscreenBackground::frameList; +QMap FullScreenBackground::blurBackgroundCacheMap; +QList FullScreenBackground::frameList; +QPointer FullScreenBackground::currentFrame = nullptr; +QPointer FullScreenBackground::currentContent = nullptr; -FullscreenBackground::FullscreenBackground(SessionBaseModel *model, QWidget *parent) +FullScreenBackground::FullScreenBackground(SessionBaseModel *model, QWidget *parent) : QWidget(parent) - , m_fadeOutAni(nullptr) - , m_imageEffectInter(new ImageEffectInter("com.deepin.daemon.ImageEffect", "/com/deepin/daemon/ImageEffect", QDBusConnection::systemBus(), this)) , m_model(model) , m_useSolidBackground(false) - , m_fadeOutAniFinished(false) - , m_enableAnimation(true) , m_blackWidget(new BlackWidget(this)) + , m_resetGeometryTimer(new QTimer(this)) + , m_shutdownBlackWidget(nullptr) { #ifndef QT_DEBUG if (!m_model->isUseWayland()) { setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); } else { - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Window); + setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Window); setAttribute(Qt::WA_NativeWindow); // 创建窗口 handle - windowHandle()->setProperty("_d_dwayland_window-type", "standAlone"); // 禁止移动 + // onScreenDisplay 低于override,高于tooltip,希望显示在锁屏上方的界面,均需要调整层级为onScreenDisplay或者override + windowHandle()->setProperty("_d_dwayland_window-type", "onScreenDisplay"); + DPlatformWindowHandle handle(this, this); + handle.setWindowRadius(-1); } #endif frameList.append(this); - m_useSolidBackground = getDConfigValue(getDefaultConfigFileName(), "useSolidBackground", false).toBool(); - m_enableAnimation = DGuiApplicationHelper::isSpecialEffectsEnvironment(); - if (m_enableAnimation && !m_useSolidBackground) { - m_fadeOutAni = new QVariantAnimation(this); - m_fadeOutAni->setEasingCurve(QEasingCurve::InOutCubic); - m_fadeOutAni->setDuration(2000); - m_fadeOutAni->setStartValue(0.0); - m_fadeOutAni->setEndValue(1.0); - - connect(m_fadeOutAni, &QVariantAnimation::valueChanged, this, [ this ] { - update(); - // 动画播放完毕后不在需要清晰的壁纸,释放资源 - if (m_fadeOutAni->currentValue() == 1.0) { - backgroundCacheList.clear(); - backgroundPath = ""; - m_fadeOutAniFinished = true; - } - }); - } + m_useSolidBackground = DConfigHelper::instance()->getConfig("useSolidBackground", false).toBool(); - connect(qApp, &QGuiApplication::primaryScreenChanged, this, [this](QScreen *screen) { - qDebug() << "QGuiApplication::primaryScreenChanged:" << m_screen << screen << m_content; - if (m_screen && m_screen == screen && m_content) { - m_primaryShowFinished = true; + m_blackWidget->setBlackMode(m_model->isBlackMode()); + connect(m_model, &SessionBaseModel::blackModeChanged, this, [this](bool is_black) { + m_blackWidget->setBlackMode(is_black); + if (currentContent) { + // 黑屏模式的时候需要隐藏中间的窗口 + currentContent->setVisible(!is_black); + currentContent->raise(); } }); + connect(m_resetGeometryTimer, &QTimer::timeout, this, [this] { + const auto ¤tGeometry = geometry(); + if (currentGeometry != m_geometryRect) { + qCWarning(DDE_SHELL) << "Geometry mismatch detected! Qt cached geometry:" << currentGeometry + << ", target geometry:" << m_geometryRect << ", this:" << this; + setGeometry(m_geometryRect); + } - m_blackWidget->setBlackMode(m_model->isBlackMode()); - connect(m_model, &SessionBaseModel::blackModeChanged, m_blackWidget, &BlackWidget::setBlackMode); + // 通过 XCB 检查窗口在 X Server 中的实际位置 + // 注意:X11 坐标系中,窗口位置不乘 DPR(与 X RandR 一致),窗口大小乘 DPR + if (!m_model->isUseWayland() && windowHandle()) { + xcb_connection_t *connection = nullptr; +#ifndef ENABLE_DSS_SNIPE + connection = QX11Info::connection(); +#else + auto *x11App = qGuiApp->nativeInterface(); + if (x11App) + connection = x11App->connection(); +#endif + if (connection) { + auto cookie = xcb_get_geometry(connection, static_cast(winId())); + auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr); + if (reply) { + QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height); + const qreal dpr = devicePixelRatioF(); + QRect expectedPhysical(m_geometryRect.x(), m_geometryRect.y(), + qRound(m_geometryRect.width() * dpr), + qRound(m_geometryRect.height() * dpr)); + if (xcbGeometry != expectedPhysical) { + qCWarning(DDE_SHELL) << "XCB position mismatch! XCB geometry(physical):" << xcbGeometry + << ", expected(physical):" << expectedPhysical + << ", target(logical):" << m_geometryRect + << ", dpr:" << dpr + << ", this:" << this + << ", screen:" << (m_screen ? m_screen->name() : "null"); + // Qt 的 geometry() 缓存可能已经是正确值,但实际 X 窗口未移动。 + // 强制重新绑定 screen 并调用 setGeometry,让 Qt 重新发送 XCB configure request。 + if (!m_screen.isNull() && windowHandle()->screen() != m_screen) { + windowHandle()->setScreen(m_screen); + } + // 先 resize 到 0,0 再设目标值,破坏 Qt 的 "geometry 未变" 优化,强制重新下发 + setGeometry(0, 0, 0, 0); + setGeometry(m_geometryRect); + } else { + qCInfo(DDE_SHELL) << "XCB position match, no need to set geometry"; + } + free(reply); + } + } + } + }); + + connect(m_model, &SessionBaseModel::shutdownkModeChanged, this, [this] (bool value){ + if (!m_shutdownBlackWidget) { + m_shutdownBlackWidget = new ShutdownBlackWidget(this); + } + qCInfo(DDE_SHELL) << "FullScreenBackground size : " << size(); + m_shutdownBlackWidget->setFixedSize(this->size()); + m_shutdownBlackWidget->setBlackMode(value); + }); } -FullscreenBackground::~FullscreenBackground() +FullScreenBackground::~FullScreenBackground() { frameList.removeAll(this); } -void FullscreenBackground::updateBackground(const QString &path) +void FullScreenBackground::updateBackground(const QString &path) { - if (m_useSolidBackground) + if (m_useSolidBackground || !isPicture(path)) return; - if (isPicture(path)) { - // 动画播放完毕不再需要清晰的背景图片 - if (!m_fadeOutAniFinished && !(backgroundPath == path && contains(PIXMAP_TYPE_BACKGROUND))) { - backgroundPath = path; - addPixmap(pixmapHandle(QPixmap(path)), PIXMAP_TYPE_BACKGROUND); - } - - // 需要播放动画的时候才更新模糊壁纸 - if (m_enableAnimation) - updateBlurBackground(path); + if (path == originBackgroundPath && !blurBackgroundPath.isEmpty()) { + updateScreenBluBackground(blurBackgroundPath); + return; } + + originBackgroundPath = path; + updateBlurBackground(path); } -void FullscreenBackground::updateBlurBackground(const QString &path) +void FullScreenBackground::updateScreenBluBackground(const QString &blurPath) { - QDBusPendingCall async = m_imageEffectInter->Get("", path); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *call) { - const QDBusPendingReply reply = *call; - if (!reply.isError()) { - QString blurPath = reply.value(); + if (!blurPath.isEmpty() && blurBackgroundPath != blurPath) { + blurBackgroundPath = blurPath; + } - if (!isPicture(blurPath)) { - blurPath = "/usr/share/backgrounds/default_background.jpg"; - } + QString scaledPath; + if (getScaledBlurImage(blurPath, scaledPath)) { + QPixmap pixmap; + loadPixmap(scaledPath, pixmap); + addPixmap(pixmap, PIXMAP_TYPE_BLUR_BACKGROUND); + } else { + handleBackground(blurBackgroundPath, PIXMAP_TYPE_BLUR_BACKGROUND); + } - if (blurBackgroundPath != blurPath || !contains(PIXMAP_TYPE_BLUR_BACKGROUND)) { - blurBackgroundPath = blurPath; - addPixmap(pixmapHandle(QPixmap(blurPath)), PIXMAP_TYPE_BLUR_BACKGROUND); - } + if (isVisible()) { + update(); + } +} - // 只播放一次动画,后续背景图片变更直接更新模糊壁纸即可 - if (m_fadeOutAni && !m_fadeOutAniFinished) - m_fadeOutAni->start(); - else - update(); - } else { - qWarning() << "get blur background image error: " << reply.error().message(); +void FullScreenBackground::updateBlurBackground(const QString &path) +{ + QDBusMessage message = QDBusMessage::createMethodCall(DSS_DBUS::imageEffectService, DSS_DBUS::imageEffectPath, + DSS_DBUS::imageEffectService, "Get"); + message << "" << path; + QDBus::CallMode callMode = isVisible() ? QDBus::BlockWithGui : QDBus::Block; + QDBusPendingReply reply = QDBusConnection::systemBus().call(message, callMode, 2 * 1000); + QString blurPath; + if (!reply.isError()) { + blurPath = reply.value(); + bool isPicture = QFile::exists(blurPath) && QFile(blurPath).size() && checkPictureCanRead(blurPath); + if (!isPicture) { + blurPath = "/usr/share/backgrounds/default_background.jpg"; } - call->deleteLater(); - }, Qt::QueuedConnection); + } else { + blurPath = "/usr/share/backgrounds/default_background.jpg"; + qCWarning(DDE_SHELL) << "Get blur background path error:" << reply.error().message(); + } + + // 处理模糊背景图和执行动画或update; + updateScreenBluBackground(blurPath); } -bool FullscreenBackground::contentVisible() const +bool FullScreenBackground::contentVisible() const { - return m_content && m_content->isVisible(); + return currentContent && currentContent->isVisible() && currentContent->parent() == this; } -void FullscreenBackground::setEnterEnable(bool enable) +void FullScreenBackground::setEnterEnable(bool enable) { m_enableEnterEvent = enable; } -void FullscreenBackground::setScreen(QPointer screen, bool isVisible) +void FullScreenBackground::setScreen(QPointer screen, bool isVisible) { - if (screen.isNull()) + if (screen.isNull()) { + qCWarning(DDE_SHELL) << "Screen is nullptr"; return; + } - QScreen *primary_screen = QGuiApplication::primaryScreen(); - if (primary_screen == screen && isVisible) { - m_content->show(); - m_primaryShowFinished = true; - emit contentVisibleChanged(true); + qCInfo(DDE_SHELL) << "Set screen:" << screen + << ", screen geometry:" << screen->geometry() + << ", full screen background object:" << this + << ", visible:" << isVisible; + if (isVisible) { + updateCurrentFrame(this); } else { - QTimer::singleShot(1000, this, [=] { - m_primaryShowFinished = true; + // 如果有多个屏幕则根据鼠标所在的屏幕来显示 + QTimer::singleShot(1000, this, [this] { setMouseTracking(true); }); } updateScreen(screen); + + // 更新屏幕后设置壁纸,这样避免处理多个尺寸的壁纸 + updateBackground(m_model->currentUser()->greeterBackground()); } -void FullscreenBackground::setContentVisible(bool visible) +void FullScreenBackground::setContent(QWidget *const w) { - if (this->contentVisible() == visible) + if (!w) { + qCWarning(DDE_SHELL) << "Content is null"; return; - - if (!m_content) + } + qCInfo(DDE_SHELL) << "Incoming content:" << w << ", current content:" << currentContent; + // 不重复设置content + if (currentContent && currentContent->isVisible() && currentContent == w && currentFrame && w->parent() == currentFrame) { + qCDebug(DDE_SHELL) << "Parent is current frame"; return; + } - if (!isVisible() && !visible) + if (!currentContent.isNull()) { + currentContent->setParent(nullptr); + currentContent->hide(); + } + currentContent = w; + if (!currentFrame) { + qCWarning(DDE_SHELL) << "Current frame is null"; return; + } - m_content->setVisible(visible); - - emit contentVisibleChanged(visible); -} - -void FullscreenBackground::setContent(QWidget *const w) -{ - m_content = w; - m_content->setParent(this); - m_content->move(0, 0); - m_content->setFocus(); - setFocusProxy(m_content); + currentContent->setParent(currentFrame); + currentContent->move(0, 0); + currentContent->resize(currentFrame->size()); + currentFrame->setFocusProxy(currentContent); + currentFrame->setFocus(); + currentFrame->activateWindow(); // 如果是黑屏状态则不置顶 - if (!m_blackWidget->isVisible()) - m_content->raise(); + if (!currentFrame->m_blackWidget->isVisible()) { + currentContent->raise(); + currentContent->show(); + }; + auto lockContent = dynamic_cast(w); + if (lockContent) + Q_EMIT lockContent->parentChanged(); } -void FullscreenBackground::setIsHibernateMode() +void FullScreenBackground::setIsHibernateMode() { updateGeometry(); - m_content->show(); - emit contentVisibleChanged(true); + updateCurrentFrame(this); } -bool FullscreenBackground::isPicture(const QString &file) +bool FullScreenBackground::isPicture(const QString &file) { - return QFile::exists(file) && QFile(file).size() && QImageReader(file).canRead(); + return QFile::exists(file) && QFile(file).size() && checkPictureCanRead(file); } -QString FullscreenBackground::getLocalFile(const QString &file) +QString FullScreenBackground::getLocalFile(const QString &file) { const QUrl url(file); return url.isLocalFile() ? url.toLocalFile() : url.url(); } -void FullscreenBackground::paintEvent(QPaintEvent *e) +void FullScreenBackground::paintEvent(QPaintEvent *e) { QWidget::paintEvent(e); QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform); - const QPixmap &background = getPixmap(PIXMAP_TYPE_BACKGROUND); - const QPixmap &blurBackground = getPixmap(PIXMAP_TYPE_BLUR_BACKGROUND); - const QRect trueRect(QPoint(0, 0), QSize(size() * devicePixelRatioF())); if (m_useSolidBackground) { painter.fillRect(trueRect, QColor(DDESESSIONCC::SOLID_BACKGROUND_COLOR)); } else { - if (m_fadeOutAni) { - const double currentAniValue = m_fadeOutAni->currentValue().toDouble(); - if (!background.isNull() && currentAniValue != 1.0) { - painter.setOpacity(1); - painter.drawPixmap(trueRect, - background, - QRect(trueRect.topLeft(), trueRect.size() * background.devicePixelRatioF())); - } - - if (!blurBackground.isNull()) { - painter.setOpacity(currentAniValue); - painter.drawPixmap(trueRect, - blurBackground, - QRect(trueRect.topLeft(), trueRect.size() * blurBackground.devicePixelRatioF())); - } + const QPixmap &blurBackground = getPixmap(PIXMAP_TYPE_BLUR_BACKGROUND); + if (blurBackground.isNull()) { + painter.fillRect(trueRect, QColor(DDESESSIONCC::SOLID_BACKGROUND_COLOR)); } else { - // 不使用的动画的过渡的时候直接绘制清晰的背景 - if (!background.isNull()) { - painter.drawPixmap(trueRect, - background, - QRect(trueRect.topLeft(), trueRect.size() * background.devicePixelRatioF())); - } + painter.drawPixmap(trueRect, + blurBackground, + QRect(trueRect.topLeft(), trueRect.size() * devicePixelRatioF())); } } } -void FullscreenBackground::tryActiveWindow(int count/* = 9*/) +void FullScreenBackground::tryActiveWindow(int count /* = 9*/) { if (count < 0 || m_model->isUseWayland()) return; @@ -287,42 +329,58 @@ void FullscreenBackground::tryActiveWindow(int count/* = 9*/) activateWindow(); - if (m_content && !m_content->isVisible()) { + if (currentContent && !currentContent->isVisible()) { qCDebug(DDE_SS) << "hide..." << count; return; } - QTimer::singleShot(50 , this, std::bind(&FullscreenBackground::tryActiveWindow, this, count -1)); + QTimer::singleShot(50, this, std::bind(&FullScreenBackground::tryActiveWindow, this, count - 1)); } -void FullscreenBackground::enterEvent(QEvent *event) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void FullScreenBackground::enterEvent(QEnterEvent *event) +#else +void FullScreenBackground::enterEvent(QEvent *event) +#endif { - if (m_primaryShowFinished && m_enableEnterEvent && m_model->visible()) { - m_content->show(); - emit contentVisibleChanged(true); + qCInfo(DDE_SS) << "Enter event, enable enter event:" << m_enableEnterEvent << ", visible:" << m_model->visible(); + if (m_enableEnterEvent && m_model->visible()) { + updateCurrentFrame(this); + // 多屏情况下,此Frame晚于其它Frame显示出来时,可能处于未激活状态(特别是在wayland环境下比较明显) + activateWindow(); } - // 锁屏截图之后 activewindow 不是锁屏了,此时发现不是 activewindow 主动尝试激活 - if (!isActiveWindow() && m_content && m_content->isVisible()) - tryActiveWindow(); + // 锁屏截图之后 active window 不是锁屏了,此时发现不是 active window 主动尝试激活 + if (!isActiveWindow() && contentVisible()) + tryActiveWindow(); return QWidget::enterEvent(event); } -void FullscreenBackground::leaveEvent(QEvent *event) +void FullScreenBackground::leaveEvent(QEvent *event) { return QWidget::leaveEvent(event); } -void FullscreenBackground::resizeEvent(QResizeEvent *event) +void FullScreenBackground::resizeEvent(QResizeEvent *event) { - m_blackWidget->resize(size()); - m_content->resize(size()); - if (isPicture(backgroundPath) && !contains(PIXMAP_TYPE_BACKGROUND)) - addPixmap(pixmapHandle(QPixmap(backgroundPath)), PIXMAP_TYPE_BACKGROUND); - if (isPicture(blurBackgroundPath) && !contains(PIXMAP_TYPE_BLUR_BACKGROUND)) - addPixmap(pixmapHandle(QPixmap(blurBackgroundPath)), PIXMAP_TYPE_BLUR_BACKGROUND); + if (!blurBackgroundCacheMap.isEmpty() && isPicture(blurBackgroundPath) && !contains(PIXMAP_TYPE_BLUR_BACKGROUND)) { + QString scaledPath; + if (getScaledBlurImage(blurBackgroundPath, scaledPath)) { + QPixmap pixmap; + loadPixmap(scaledPath, pixmap); + addPixmap(pixmap, PIXMAP_TYPE_BLUR_BACKGROUND); + } else { + handleBackground(blurBackgroundPath, PIXMAP_TYPE_BLUR_BACKGROUND); + } + } updatePixmap(); + + m_blackWidget->resize(size()); + if (currentFrame == this && currentContent) { + currentContent->resize(size()); + } + QWidget::resizeEvent(event); } @@ -331,17 +389,16 @@ void FullscreenBackground::resizeEvent(QResizeEvent *event) * * @param event */ -void FullscreenBackground::mouseMoveEvent(QMouseEvent *event) +void FullScreenBackground::mouseMoveEvent(QMouseEvent *event) { - if (m_model->visible()) { - m_content->show(); - emit contentVisibleChanged(true); + if (m_model->visible() && m_enableEnterEvent) { + updateCurrentFrame(this); } QWidget::mouseMoveEvent(event); } -void FullscreenBackground::keyPressEvent(QKeyEvent *e) +void FullScreenBackground::keyPressEvent(QKeyEvent *e) { QWidget::keyPressEvent(e); @@ -356,77 +413,114 @@ void FullscreenBackground::keyPressEvent(QKeyEvent *e) } } -void FullscreenBackground::showEvent(QShowEvent *event) +void FullScreenBackground::showEvent(QShowEvent *event) { + qCDebug(DDE_SHELL) << "Frame is already displayed:" << this; if (m_model->isUseWayland()) { Q_EMIT requestDisableGlobalShortcutsForWayland(true); } - if (QWindow *w = windowHandle()) { - if (m_screen) { - if (w->screen() != m_screen) { - w->setScreen(m_screen); - } - - // 更新窗口位置和大小 - updateGeometry(); - } else { - updateScreen(w->screen()); - } + // fix bug 155019 此处是针对wayland下屏保退出,因qt没有发送enterEvent事件,进而导致密码框没有显示的规避方案 + // x下面先激活其它窗口右键菜单,锁屏后,再激活dock右键菜单自动锁屏后,同样存在没有发送enterEvent事件的问题 + // 如果鼠标的位置在当前屏幕内且锁屏状态为显示,将密码框显示出来 + if (m_model->visible() && geometry().contains(QCursor::pos())) { + currentContent->show(); + // 多屏情况下,此Frame晚于其它Frame显示出来时,可能处于未激活状态(特别是在wayland环境下比较明显) + activateWindow(); + } - if (!m_model->isUseWayland()) { - connect(w, &QWindow::screenChanged, this, &FullscreenBackground::updateScreen, Qt::DirectConnection); - } +#ifndef ENABLE_DSS_SNIPE + // setScreen中有设置updateGeometry,单屏不需要再次设置 + if (qApp->screens().size() > 1) { + updateGeometry(); } +#else + updateGeometry(); +#endif + + // 显示的时候需要置顶,截图在上方的话无法显示锁屏 见Bug-140545 + raise(); + + m_blackWidget->setBlackMode(m_model->isBlackMode()); return QWidget::showEvent(event); } -void FullscreenBackground::hideEvent(QHideEvent *event) +void FullScreenBackground::hideEvent(QHideEvent *event) { + qCDebug(DDE_SHELL) << "Frame is hidden:" << this; if (m_model->isUseWayland()) { Q_EMIT requestDisableGlobalShortcutsForWayland(false); } + QWidget::hideEvent(event); } -const QPixmap FullscreenBackground::pixmapHandle(const QPixmap &pixmap) +void FullScreenBackground::updateScreen(QPointer screen) { - const QSize trueSize {size() * devicePixelRatioF()}; - QPixmap pix; - if (!pixmap.isNull()) - pix = pixmap.scaled(trueSize, Qt::KeepAspectRatioByExpanding, Qt::FastTransformation); + if (screen == m_screen) + return; - pix = pix.copy(QRect((pix.width() - trueSize.width()) / 2, - (pix.height() - trueSize.height()) / 2, - trueSize.width(), - trueSize.height())); + if (!m_screen.isNull()) + disconnect(m_screen, &QScreen::geometryChanged, this, &FullScreenBackground::updateGeometry); - // draw pix to widget, so pix need set pixel ratio from qwidget devicepixelratioF - pix.setDevicePixelRatio(devicePixelRatioF()); + if (!screen.isNull()) { + connect(screen, &QScreen::geometryChanged, this, &FullScreenBackground::updateGeometry); + } + + m_screen = screen; - return pix; + updateGeometry(); } -void FullscreenBackground::updateScreen(QScreen *screen) +void FullScreenBackground::updateGeometry() { - if (screen == m_screen) + if (m_screen.isNull()) { return; + } - if (m_screen) - disconnect(m_screen, &QScreen::geometryChanged, this, &FullscreenBackground::updateGeometry); - - if (screen) - connect(screen, &QScreen::geometryChanged, this, &FullscreenBackground::updateGeometry); + qCInfo(DDE_SHELL) << "Set background screen:" << m_screen << ", geometry:" << m_screen->geometry(); + + // for bug:184943.系统修改分辨率后,登录界面获取的屏幕分辨率不正确,通过xrandr获取屏幕分辨率 + if (m_model->appType() == AuthCommon::Login && !m_model->isUseWayland()) { + const auto screensGeometry = getScreenGeometryByXrandr(); + + if (screensGeometry.contains(m_screen->name())) { + // 如果qt获取的屏幕分辨率和xrandr获取的屏幕分辨率一致,使用qt获取的屏幕geometry + QSize qtScreenSize = m_screen->size(); + QSize xrandrScreenSize = screensGeometry[m_screen->name()].size(); + if (qtScreenSize == xrandrScreenSize) { + // fix205519。获取到的屏幕尺寸一致,但qt的位置可能是错的,但不影响窗口位置。 + setddeGeometry(m_screen->geometry()); + } else { + setddeGeometry(screensGeometry[m_screen->name()]); + qCDebug(DDE_SHELL) << "Set geometry by xrandr, this:" << this << screensGeometry[m_screen->name()] + << " screen:" << m_screen->name() << "screen geometry:" << m_screen->geometry(); + } + } else { + setddeGeometry(m_screen->geometry()); + } - m_screen = screen; - if (m_screen) - updateGeometry(); -} + return; + } -void FullscreenBackground::updateGeometry() -{ - qInfo() << "set background geometry:" << m_screen << m_screen->geometry(); - setGeometry(m_screen->geometry()); + if (!m_screen.isNull()) { + // X11 下也需要将 QWindow 关联到正确的 QScreen,否则 Qt 可能将窗口归属到错误的 screen + if (windowHandle() && windowHandle()->screen() != m_screen) { + qCInfo(DDE_SHELL) << "bindWindowToScreen, windowHandle screen:" << windowHandle()->screen()->name() + << ", target screen:" << m_screen->name() << ", this:" << this; + windowHandle()->setScreen(m_screen); + } + setddeGeometry(m_screen->geometry()); + + qCInfo(DDE_SHELL) << "Update geometry, screen:" << m_screen + << ", screen name:" << m_screen->name() + << ", screen geometry:" << m_screen->geometry() + << ", lockFrame:" << this + << ", frame geometry:" << this->geometry() + << ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null"); + } else { + qCWarning(DDE_SHELL) << "Screen is nullptr"; + } } /******************************************************** @@ -434,108 +528,288 @@ void FullscreenBackground::updateGeometry() * 用户登录界面,主窗体在某时刻会被设置为WindowDeactivate, * 此时登录界面获取不到焦点,需要调用requestActivate激活窗体。 ********************************************************/ -bool FullscreenBackground::event(QEvent *e) +bool FullScreenBackground::event(QEvent *e) { #ifndef QT_DEBUG if (e->type() == QEvent::WindowDeactivate) { - if (m_content->isVisible()) { + if (contentVisible()) { tryActiveWindow(); } } #endif + + if (e->type() == QEvent::MouseButtonPress) { + setFocus(); + } + return QWidget::event(e); } -const QPixmap& FullscreenBackground::getPixmap(int type) +const QPixmap &FullScreenBackground::getPixmap(int type) { - static QPixmap pixmap; + static QPixmap nullPixmap; - const QSize &size = trueSize(); - auto findPixmap = [size](QList> &list) -> const QPixmap & { - auto it = std::find_if(list.begin(), list.end(), - [size](QPair pair) { return pair.first == size; }); - return it != list.end() ? it.i->t().second : pixmap; - }; + QString strSize = sizeToString(trueSize()); + if (PIXMAP_TYPE_BLUR_BACKGROUND == type && blurBackgroundCacheMap.contains(strSize)) { + return blurBackgroundCacheMap[strSize]; + } - if (PIXMAP_TYPE_BACKGROUND == type) - return findPixmap(backgroundCacheList); - else - return findPixmap(blurBackgroundCacheList); + return nullPixmap; } -QSize FullscreenBackground::trueSize() const +QSize FullScreenBackground::trueSize() const { return size() * devicePixelRatioF(); } /** - * @brief FullscreenBackground::addPixmap + * @brief FullScreenBackground::addPixmap * 新增pixmap,存在相同size的则替换,没有则新增 * @param pixmap pixmap对象 * @param type 清晰壁纸还是模糊壁纸 */ -void FullscreenBackground::addPixmap(const QPixmap &pixmap, const int type) -{ - const QSize &size = trueSize(); - auto addFunc = [ this, &pixmap, size ] (QList> &list){ - bool exist = false; - for (auto &pair : list) { - if (pair.first == size) { - pair.second = pixmap; - exist = true; - } - } - if (!exist) - list.append(QPair(trueSize(), pixmap)); - }; - - if (PIXMAP_TYPE_BACKGROUND == type) - addFunc(backgroundCacheList); - else - addFunc(blurBackgroundCacheList); +void FullScreenBackground::addPixmap(const QPixmap &pixmap, const int type) +{ + QString strSize = sizeToString(trueSize()); + if (type == PIXMAP_TYPE_BLUR_BACKGROUND) { + blurBackgroundCacheMap[strSize] = pixmap; + } } /** - * @brief FullscreenBackground::updatePixmap + * @brief FullScreenBackground::updatePixmap * 更新壁纸列表,移除当前所有屏幕都不会使用的壁纸数据 */ -void FullscreenBackground::updatePixmap() +void FullScreenBackground::updatePixmap() { - auto isNoUsefunc = [](const QSize &size) -> bool { - bool b = std::any_of(frameList.begin(), frameList.end(), [size](FullscreenBackground *frame) { - return frame->trueSize() == size; - }); - return !b; + auto removeNotUsedPixmap = [](QMap &cacheMap, const QStringList &frameSizeList) { + QStringList cacheMapKeys = cacheMap.keys(); + for (auto &key : cacheMapKeys) { + if (!frameSizeList.contains(key)) { + qCInfo(DDE_SHELL) << "Remove not used pixmap:" << key; + cacheMap.remove(key); + } + } }; - auto updateFunc = [ isNoUsefunc ] (QList> &list) { - for (auto &pair : list) { - if (isNoUsefunc(pair.first)) - list.removeAll(pair); + QStringList frameSizeList; + for (auto &frame : frameList) { + QString strSize = sizeToString(frame->trueSize()); + frameSizeList.append(strSize); + } + + removeNotUsedPixmap(blurBackgroundCacheMap, frameSizeList); +} + +bool FullScreenBackground::contains(int type) +{ + auto containPixmap = [](const QMap &cacheMap, const QString &strSize) { + if (cacheMap.contains(strSize)) { + const QPixmap &pixmap = cacheMap[strSize]; + return !pixmap.isNull(); // pixmap 为空也返回false + } else { + return false; } }; - updateFunc(backgroundCacheList); - updateFunc(blurBackgroundCacheList); + QString strSize = sizeToString(trueSize()); + if (PIXMAP_TYPE_BLUR_BACKGROUND == type) { + return containPixmap(blurBackgroundCacheMap, strSize); + } + return false; } -bool FullscreenBackground::contains(int type) +void FullScreenBackground::moveEvent(QMoveEvent *event) { - auto containsFunc = [this](QList> &list) -> bool { - bool b = std::any_of(list.begin(), list.end(), [this](QPair &pair) { - return pair.first == trueSize(); - }); - return b; - }; + // 规避 bug189309,登录时后端屏幕变化通知太晚 + if (currentContent && !currentContent->isVisible()) { + if (m_model->isUseWayland()) { + if (m_model->visible() && geometry().contains(QCursor::pos())) { + currentContent->show(); + } + } + } + QWidget::moveEvent(event); +} + +QMap FullScreenBackground::getScreenGeometryByXrandr() +{ + QMap screensGeometry; + + // 获取缩放比例 + double scale = getScaleFactorFromDisplay(); + double scaleFromDisplayQt = qApp->devicePixelRatio(); + qCInfo(DDE_SHELL) << "Get scale factor from display scale:" << scale << " scale from display qt:" << scaleFromDisplayQt; + // 如果获取失败或者与从Qt获取的不一致,则不需要处理,使用Qt的屏幕信息 + if (scale <= 0 || scaleFromDisplayQt != scale) { + return screensGeometry; + } + + // 启动 xrandr | grep connected 进程 + QProcess process; + QStringList arguments; + arguments << "-c" + << "xrandr | grep connected"; + process.start("/bin/sh", arguments); + process.waitForStarted(); + process.waitForFinished(); + + // 读取进程输出并解析屏幕信息 + QString output = QString::fromLocal8Bit(process.readAll()); + QRegularExpression regex("(\\S+) connected (?:primary )?(\\d+)x(\\d+)\\+(\\d+)\\+(\\d+)"); + QRegularExpressionMatchIterator iter = regex.globalMatch(output); + while (iter.hasNext()) { + QRegularExpressionMatch match = iter.next(); + if (match.hasMatch()) { + QString name = match.captured(1); + int width = match.captured(2).toInt(); + int height = match.captured(3).toInt(); + int x = match.captured(4).toInt(); + int y = match.captured(5).toInt(); + QRect rect(x, y, width / scale, height / scale); + screensGeometry.insert(name, rect); + qCInfo(DDE_SHELL) << "Screen name:" << name << ", screen rect:" << rect; + } + } - if (PIXMAP_TYPE_BACKGROUND == type) - return containsFunc(backgroundCacheList); + return screensGeometry; +} + +double FullScreenBackground::getScaleFactorFromDisplay() +{ + QDBusInterface display(DSS_DBUS::systemDisplayService, + DSS_DBUS::systemDisplayPath, + DSS_DBUS::systemDisplayService, + QDBusConnection::systemBus(), this); + + QDBusReply reply = display.call("GetConfig"); + QString jsonObjStr = reply.value(); + if (jsonObjStr.isNull()) { + qCWarning(DDE_SHELL) << "Greeter get system display config failed (`GetConfig` null)"; + return -1.0; + } + + // 获取 ScaleFactors 对象 + QJsonObject json = QJsonDocument::fromJson(jsonObjStr.toUtf8()).object(); + QJsonObject scaleFactors = json.value("Config").toObject().value("ScaleFactors").toObject(); + + // 遍历 ScaleFactors 对象 + for (const auto &key : scaleFactors.keys()) { + return scaleFactors.value(key).toDouble(); + } + + qCWarning(DDE_SHELL) << "greeter get system display config failed(`scaleFactors` null)"; + return -1.0; +} + +void FullScreenBackground::updateCurrentFrame(FullScreenBackground *frame) +{ + if (!frame) { + qCWarning(DDE_SHELL) << "Update current frame failed, frame is null"; + return; + } + + if (frame->m_screen) + qCInfo(DDE_SHELL) << "Update current frame:" << frame << ", screen:" << frame->m_screen->name(); else - return containsFunc(blurBackgroundCacheList); + qWarning() << "Frame's screen is null, frame:" << frame; + + currentFrame = frame; + setContent(currentContent); } -void FullscreenBackground::moveEvent(QMoveEvent *event) +void FullScreenBackground::handleBackground(const QString &path, int type) { - qInfo() << "FullscreenBackground::moveEvent: " << ", old pos: " << event->oldPos() << ", pos: " << event->pos(); - QWidget::moveEvent(event); -} \ No newline at end of file + QSize trueSize = this->trueSize(); + + QPixmap pixmap; + loadPixmap(path, pixmap); + + pixmap = pixmap.scaled(trueSize, Qt::KeepAspectRatioByExpanding, Qt::FastTransformation); + pixmap = pixmap.copy(QRect((pixmap.width() - trueSize.width()) / 2, + (pixmap.height() - trueSize.height()) / 2, + trueSize.width(), + trueSize.height())); + + // draw pix to widget, so pix need set pixel ratio from qwidget devicepixelratioF + pixmap.setDevicePixelRatio(devicePixelRatioF()); + addPixmap(pixmap, type); +} + +QString FullScreenBackground::sizeToString(const QSize &size) +{ + return QString("%1x%2").arg(size.width()).arg(size.height()); +} + +bool FullScreenBackground::getScaledBlurImage(const QString &originPath, QString &scaledPath) +{ +#ifndef ENABLE_DSS_SNIPE + // 为了兼容没有安装壁纸服务环境;Qt5.15高版本可以使用activatableServiceNames()遍历然后可判断系统有没有安装服务 + const QString wallpaperServicePath = "/lib/systemd/system/dde-wallpaper-cache.service"; + if (!QFile::exists(wallpaperServicePath)) { + qWarning() << "dde-wallpaper-cache service not existed"; + return false; + } +#endif + + // 壁纸服务dde-wallpaper-cache + QDBusInterface wallpaperCacheInterface("org.deepin.dde.WallpaperCache", "/org/deepin/dde/WallpaperCache", + "org.deepin.dde.WallpaperCache", QDBusConnection::systemBus()); +#ifdef ENABLE_DSS_SNIPE + if (!wallpaperCacheInterface.isValid()) { + qWarning() << "dde-wallpaper-cache service not existed"; + return false; + } +#endif + + QFile file(originPath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open file."; + return false; + } + const int fd = file.handle(); + if (fd <= 0) { + qWarning() << "originPath file fd error"; + return false; + } + + QDBusUnixFileDescriptor dbusFd(fd); + const QString &pathmd5 = QCryptographicHash::hash(originPath.toUtf8(), QCryptographicHash::Md5).toHex(); + QVariantList sizeArray; + sizeArray << QVariant::fromValue(this->trueSize()); + QDBusReply pathList = wallpaperCacheInterface.call("GetProcessedImagePathByFd", QVariant::fromValue(dbusFd), pathmd5, sizeArray); + if (pathList.value().isEmpty()) { + qWarning() << "GetProcessedImagePathByFd interface return null"; + return false; + } + + file.close(); + + QString path = pathList.value().at(0); + if (!path.isEmpty() && path != originPath) { + scaledPath = path; + // 图片处理完之后会添加_xxxx尺寸后缀,升级场景第一次登录只能获取到正在处理的原生图片,此时不能进行设置 + if (!path.contains("_")) { + return false; + } + qDebug() << "get scaled path:" << path; + return true; + } + + return false; +} + +//增加一个定时器,每隔50ms再设置一次Geometry,避免出现xorg初始化未完成的情况,导致界面显示不全 +void FullScreenBackground::setddeGeometry(const QRect &rect) +{ + qCInfo(DDE_SHELL) << "setddeGeometry called, this:" << this + << ", target rect:" << rect + << ", current geometry:" << geometry() + << ", screen:" << (m_screen ? m_screen->name() : "null") + << ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null") + << ", dpr:" << devicePixelRatioF(); + setGeometry(rect); + m_geometryRect = rect; + m_resetGeometryTimer->start(200); + QTimer::singleShot(400 * 5, m_resetGeometryTimer, &QTimer::stop); +} diff --git a/src/widgets/fullscreenbackground.h b/src/widgets/fullscreenbackground.h index efc47d51..8b89989e 100644 --- a/src/widgets/fullscreenbackground.h +++ b/src/widgets/fullscreenbackground.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef FULLSCREENBACKGROUND_H #define FULLSCREENBACKGROUND_H @@ -29,39 +8,41 @@ #include #include #include -Q_DECLARE_LOGGING_CATEGORY(DDE_SS) +#include +#include +#include -#include +#include "abstractfullbackgroundinterface.h" +#include "shutdown_black_widget.h" -using ImageEffectInter = com::deepin::daemon::ImageEffect; +Q_DECLARE_LOGGING_CATEGORY(DDE_SS) class BlackWidget; class SessionBaseModel; -class FullscreenBackground : public QWidget +class FullScreenBackground : public QWidget, public AbstractFullBackgroundInterface { Q_OBJECT - Q_PROPERTY(bool contentVisible READ contentVisible WRITE setContentVisible NOTIFY contentVisibleChanged) + Q_PROPERTY(bool contentVisible READ contentVisible) public: - explicit FullscreenBackground(SessionBaseModel *model, QWidget *parent = nullptr); - ~FullscreenBackground() override; + explicit FullScreenBackground(SessionBaseModel *model, QWidget *parent = nullptr); + ~FullScreenBackground() override; bool contentVisible() const; void setEnterEnable(bool enable); + static void setContent(QWidget *const w); public slots: void updateBackground(const QString &path); void updateBlurBackground(const QString &path); - void setScreen(QPointer screen, bool isVisible = true); - void setContentVisible(bool visible); + void setScreen(QPointer screen, bool isVisible = true) override; void setIsHibernateMode(); signals: - void contentVisibleChanged(bool contentVisible); void requestDisableGlobalShortcutsForWayland(bool enable); + void requestLockFrameHide(); protected: - void setContent(QWidget *const w); void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; void showEvent(QShowEvent *event) override; void hideEvent(QHideEvent *event) override; @@ -71,11 +52,14 @@ public slots: private: void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *event) Q_DECL_OVERRIDE; +#else void enterEvent(QEvent *event) Q_DECL_OVERRIDE; +#endif void leaveEvent(QEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - const QPixmap pixmapHandle(const QPixmap &pixmap); - void updateScreen(QScreen *screen); + void updateScreen(QPointer screen); void updateGeometry(); bool isPicture(const QString &file); QString getLocalFile(const QString &file); @@ -85,28 +69,35 @@ public slots: static void updatePixmap(); bool contains(int type); void tryActiveWindow(int count = 9); + QMap getScreenGeometryByXrandr(); + double getScaleFactorFromDisplay(); + static void updateCurrentFrame(FullScreenBackground *frame); + bool getScaledBlurImage(const QString &originPath, QString &scaledPath); + void setddeGeometry(const QRect &rect); + void updateScreenBluBackground(const QString &path); -private: - static QString backgroundPath; // 高清背景图片路径 - static QString blurBackgroundPath; // 模糊背景图片路径 +protected: + static QPointer currentContent; + static QList frameList; + static QPointer currentFrame; - static QList> backgroundCacheList; - static QList> blurBackgroundCacheList; - static QList frameList; + void handleBackground(const QString &path, int type); + static QString sizeToString(const QSize &size); - QVariantAnimation *m_fadeOutAni; // 背景动画 - ImageEffectInter *m_imageEffectInter; // 获取模糊背景服务 +private: + static QString originBackgroundPath; // 原图路径 + static QString blurBackgroundPath; // 模糊背景图片路径 + static QMap blurBackgroundCacheMap; - QPointer m_content; QPointer m_screen; SessionBaseModel *m_model = nullptr; - bool m_primaryShowFinished = false; bool m_enableEnterEvent = true; bool m_useSolidBackground; - bool m_fadeOutAniFinished; - bool m_enableAnimation; BlackWidget *m_blackWidget; + QTimer *m_resetGeometryTimer; + QRect m_geometryRect; + ShutdownBlackWidget *m_shutdownBlackWidget; }; #endif // FULLSCREENBACKGROUND_H diff --git a/src/widgets/img/back-hover.svg b/src/widgets/img/back-hover.svg new file mode 100644 index 00000000..a5948f1a --- /dev/null +++ b/src/widgets/img/back-hover.svg @@ -0,0 +1,13 @@ + + + 编组 + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/back-normal.svg b/src/widgets/img/back-normal.svg new file mode 100644 index 00000000..c410397d --- /dev/null +++ b/src/widgets/img/back-normal.svg @@ -0,0 +1,17 @@ + + + 编组 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/inhibitview/cancel_hover.svg b/src/widgets/img/inhibitview/cancel_hover.svg new file mode 100644 index 00000000..9736b26f --- /dev/null +++ b/src/widgets/img/inhibitview/cancel_hover.svg @@ -0,0 +1,13 @@ + + + 画板 + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/inhibitview/cancel_normal.svg b/src/widgets/img/inhibitview/cancel_normal.svg new file mode 100644 index 00000000..8eef4095 --- /dev/null +++ b/src/widgets/img/inhibitview/cancel_normal.svg @@ -0,0 +1,15 @@ + + + 画板 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/inhibitview/logout_warning.svg b/src/widgets/img/inhibitview/logout_warning.svg new file mode 100644 index 00000000..d2cbb06e --- /dev/null +++ b/src/widgets/img/inhibitview/logout_warning.svg @@ -0,0 +1,11 @@ + + + Fill 4 + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/inhibitview/poweroff_warning.svg b/src/widgets/img/inhibitview/poweroff_warning.svg new file mode 100644 index 00000000..ede2bb73 --- /dev/null +++ b/src/widgets/img/inhibitview/poweroff_warning.svg @@ -0,0 +1,9 @@ + + + 画板 + + + + + + \ No newline at end of file diff --git a/src/widgets/img/inhibitview/reboot_warning.svg b/src/widgets/img/inhibitview/reboot_warning.svg new file mode 100644 index 00000000..303e1d49 --- /dev/null +++ b/src/widgets/img/inhibitview/reboot_warning.svg @@ -0,0 +1,11 @@ + + + Fill 6 + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/screen_keyboard_hover.svg b/src/widgets/img/screen_keyboard_hover.svg index 8ea7bd1b..d194cad2 100644 --- a/src/widgets/img/screen_keyboard_hover.svg +++ b/src/widgets/img/screen_keyboard_hover.svg @@ -1,3 +1,11 @@ - - - + + + screen_keyboard_hover + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/screen_keyboard_normal.svg b/src/widgets/img/screen_keyboard_normal.svg index 85d9249c..58550a75 100644 --- a/src/widgets/img/screen_keyboard_normal.svg +++ b/src/widgets/img/screen_keyboard_normal.svg @@ -1,3 +1,10 @@ - - - + + + screen_keyboard_normal + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/screen_keyboard_press.svg b/src/widgets/img/screen_keyboard_press.svg index c2f9586d..ff962f5b 100644 --- a/src/widgets/img/screen_keyboard_press.svg +++ b/src/widgets/img/screen_keyboard_press.svg @@ -1,3 +1,10 @@ - - - + + + screen_keyboard_press + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/update/failed.svg b/src/widgets/img/update/failed.svg new file mode 100644 index 00000000..323734da --- /dev/null +++ b/src/widgets/img/update/failed.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/widgets/img/update/logo.svg b/src/widgets/img/update/logo.svg new file mode 100644 index 00000000..16b1375c --- /dev/null +++ b/src/widgets/img/update/logo.svg @@ -0,0 +1,17 @@ + + + 编组 2 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/update/success.svg b/src/widgets/img/update/success.svg new file mode 100644 index 00000000..7e03506c --- /dev/null +++ b/src/widgets/img/update/success.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/widgets/img/update/waiting_update/waiting_update_0.png b/src/widgets/img/update/waiting_update/waiting_update_0.png new file mode 100644 index 00000000..6610c81e Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_0.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_1.png b/src/widgets/img/update/waiting_update/waiting_update_1.png new file mode 100644 index 00000000..dc0e53e3 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_1.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_10.png b/src/widgets/img/update/waiting_update/waiting_update_10.png new file mode 100644 index 00000000..5b184db9 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_10.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_11.png b/src/widgets/img/update/waiting_update/waiting_update_11.png new file mode 100644 index 00000000..48d79397 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_11.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_12.png b/src/widgets/img/update/waiting_update/waiting_update_12.png new file mode 100644 index 00000000..aa10ae2f Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_12.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_13.png b/src/widgets/img/update/waiting_update/waiting_update_13.png new file mode 100644 index 00000000..9e133a80 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_13.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_14.png b/src/widgets/img/update/waiting_update/waiting_update_14.png new file mode 100644 index 00000000..44ead256 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_14.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_15.png b/src/widgets/img/update/waiting_update/waiting_update_15.png new file mode 100644 index 00000000..9289c284 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_15.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_16.png b/src/widgets/img/update/waiting_update/waiting_update_16.png new file mode 100644 index 00000000..0fca04fb Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_16.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_17.png b/src/widgets/img/update/waiting_update/waiting_update_17.png new file mode 100644 index 00000000..c6c22ee9 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_17.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_18.png b/src/widgets/img/update/waiting_update/waiting_update_18.png new file mode 100644 index 00000000..bc0a2368 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_18.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_19.png b/src/widgets/img/update/waiting_update/waiting_update_19.png new file mode 100644 index 00000000..b01890b6 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_19.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_2.png b/src/widgets/img/update/waiting_update/waiting_update_2.png new file mode 100644 index 00000000..cdb069ca Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_2.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_20.png b/src/widgets/img/update/waiting_update/waiting_update_20.png new file mode 100644 index 00000000..cad74eae Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_20.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_21.png b/src/widgets/img/update/waiting_update/waiting_update_21.png new file mode 100644 index 00000000..c321defa Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_21.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_22.png b/src/widgets/img/update/waiting_update/waiting_update_22.png new file mode 100644 index 00000000..86370d8e Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_22.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_23.png b/src/widgets/img/update/waiting_update/waiting_update_23.png new file mode 100644 index 00000000..80869953 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_23.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_24.png b/src/widgets/img/update/waiting_update/waiting_update_24.png new file mode 100644 index 00000000..dbb0205d Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_24.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_25.png b/src/widgets/img/update/waiting_update/waiting_update_25.png new file mode 100644 index 00000000..ab3220a9 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_25.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_26.png b/src/widgets/img/update/waiting_update/waiting_update_26.png new file mode 100644 index 00000000..28433af6 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_26.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_27.png b/src/widgets/img/update/waiting_update/waiting_update_27.png new file mode 100644 index 00000000..5eccf1a8 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_27.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_28.png b/src/widgets/img/update/waiting_update/waiting_update_28.png new file mode 100644 index 00000000..950fa166 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_28.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_29.png b/src/widgets/img/update/waiting_update/waiting_update_29.png new file mode 100644 index 00000000..31fa94c2 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_29.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_3.png b/src/widgets/img/update/waiting_update/waiting_update_3.png new file mode 100644 index 00000000..bc4451e7 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_3.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_30.png b/src/widgets/img/update/waiting_update/waiting_update_30.png new file mode 100644 index 00000000..8581cc49 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_30.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_31.png b/src/widgets/img/update/waiting_update/waiting_update_31.png new file mode 100644 index 00000000..5a02943a Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_31.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_32.png b/src/widgets/img/update/waiting_update/waiting_update_32.png new file mode 100644 index 00000000..7fcfa912 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_32.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_33.png b/src/widgets/img/update/waiting_update/waiting_update_33.png new file mode 100644 index 00000000..6ca14540 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_33.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_34.png b/src/widgets/img/update/waiting_update/waiting_update_34.png new file mode 100644 index 00000000..5ef0b35e Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_34.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_35.png b/src/widgets/img/update/waiting_update/waiting_update_35.png new file mode 100644 index 00000000..c90e8a55 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_35.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_36.png b/src/widgets/img/update/waiting_update/waiting_update_36.png new file mode 100644 index 00000000..35d6061f Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_36.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_37.png b/src/widgets/img/update/waiting_update/waiting_update_37.png new file mode 100644 index 00000000..16c1dff3 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_37.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_38.png b/src/widgets/img/update/waiting_update/waiting_update_38.png new file mode 100644 index 00000000..293191ce Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_38.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_39.png b/src/widgets/img/update/waiting_update/waiting_update_39.png new file mode 100644 index 00000000..618e8456 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_39.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_4.png b/src/widgets/img/update/waiting_update/waiting_update_4.png new file mode 100644 index 00000000..d4787ec5 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_4.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_5.png b/src/widgets/img/update/waiting_update/waiting_update_5.png new file mode 100644 index 00000000..a7ae46b1 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_5.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_6.png b/src/widgets/img/update/waiting_update/waiting_update_6.png new file mode 100644 index 00000000..d2917dec Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_6.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_7.png b/src/widgets/img/update/waiting_update/waiting_update_7.png new file mode 100644 index 00000000..c0f83f33 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_7.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_8.png b/src/widgets/img/update/waiting_update/waiting_update_8.png new file mode 100644 index 00000000..2d2844e1 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_8.png differ diff --git a/src/widgets/img/update/waiting_update/waiting_update_9.png b/src/widgets/img/update/waiting_update/waiting_update_9.png new file mode 100644 index 00000000..52f3d8f1 Binary files /dev/null and b/src/widgets/img/update/waiting_update/waiting_update_9.png differ diff --git a/src/widgets/img/user_name.svg b/src/widgets/img/user_name.svg new file mode 100644 index 00000000..2bfc109a --- /dev/null +++ b/src/widgets/img/user_name.svg @@ -0,0 +1,14 @@ + + + 小图 + + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/img/warning.svg b/src/widgets/img/warning.svg new file mode 100644 index 00000000..af8a6294 --- /dev/null +++ b/src/widgets/img/warning.svg @@ -0,0 +1,29 @@ + + + warning + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/widgets/inhibitbutton.cpp b/src/widgets/inhibitbutton.cpp new file mode 100644 index 00000000..c0c5f844 --- /dev/null +++ b/src/widgets/inhibitbutton.cpp @@ -0,0 +1,186 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "inhibitbutton.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +const int penWidth = 2; + +InhibitButton::InhibitButton(QWidget *parent) + : QWidget(parent) + , m_isSelected(false) + , m_state(Leave) + , m_iconLabel(new QLabel(this)) + , m_textLabel(new QLabel(this)) +{ + m_iconLabel->setFixedSize(64, 64); + m_textLabel->setFixedHeight(64); + + m_iconLabel->setAlignment(Qt::AlignmentFlag::AlignRight | Qt::AlignmentFlag::AlignVCenter); + m_textLabel->setAlignment(Qt::AlignmentFlag::AlignLeft | Qt::AlignmentFlag::AlignVCenter); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(m_iconLabel); + layout->setSpacing(20); + layout->addWidget(m_textLabel); + + QPalette palette = this->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + this->setPalette(palette); + + this->setLayout(layout); +} + +InhibitButton::~InhibitButton() +{ + +} + +void InhibitButton::setText(const QString &text) +{ + m_textLabel->setText(text); +} + +QString InhibitButton::text() +{ + return m_textLabel->text(); +} + +void InhibitButton::setNormalPixmap(const QPixmap &normalPixmap) +{ + m_normalPixmap = normalPixmap; +} + +void InhibitButton::setHoverPixmap(const QPixmap &hoverPixmap) +{ + m_hoverPixmap = hoverPixmap; +} + +QPixmap InhibitButton::hoverPixmap() +{ + return m_hoverPixmap; +} + +QPixmap InhibitButton::normalPixmap() +{ + return m_normalPixmap; +} + +void InhibitButton::setState(State state) +{ + m_state = state; +} + +void InhibitButton::setSelected(bool isSelected) +{ + m_isSelected = isSelected; + setState(isSelected ? Enter : Leave); + QPalette palette = this->palette(); + palette.setColor(QPalette::WindowText, m_isSelected ? Qt::black : Qt::white); + this->setPalette(palette); + + m_iconLabel->setPixmap(m_isSelected ? m_hoverPixmap : m_normalPixmap); + update(); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void InhibitButton::enterEvent(QEnterEvent *event) +#else +void InhibitButton::enterEvent(QEvent *event) +#endif +{ + m_state = Enter; + m_isSelected = true; + QPalette palette = this->palette(); + palette.setColor(QPalette::WindowText, Qt::black); + this->setPalette(palette); + + m_iconLabel->setPixmap(m_hoverPixmap); + Q_EMIT mouseEnter(); + + QWidget::enterEvent(event); + update(); +} + +void InhibitButton::leaveEvent(QEvent *event) +{ + m_state = Leave; + m_isSelected = false; + QPalette palette = this->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + this->setPalette(palette); + + m_iconLabel->setPixmap(m_normalPixmap); + Q_EMIT mouseLeave(); + + QWidget::leaveEvent(event); + update(); +} + +void InhibitButton::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + + QPalette palette = this->palette(); + QColor color = palette.color(QPalette::Text); + switch (m_state) { + case Enter: + case Release: + color.setAlphaF(0.3); + break; + case Leave: + case Press: + color.setAlphaF(0.1); + break; + } + painter.setBrush(color); + + QStyleOption opt; + opt.initFrom(this); + if (opt.state & QStyle::State_HasFocus) { + QPen pen; + pen.setWidth(penWidth); + color.setAlphaF(0.5); + pen.setColor(color); + painter.setPen(pen); + } else + painter.setPen(Qt::NoPen); + + painter.drawRoundedRect(rect().marginsRemoved(QMargins(penWidth, penWidth, penWidth, penWidth)), 18, 18); + + QWidget::paintEvent(event); +} + +void InhibitButton::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + emit clicked(); + return; +} + +void InhibitButton::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + emit clicked(); + break; + } + QWidget::keyPressEvent(event); +} + +void InhibitButton::showEvent(QShowEvent *event) +{ + m_iconLabel->setPixmap(m_normalPixmap); + QWidget::showEvent(event); +} diff --git a/src/widgets/inhibitbutton.h b/src/widgets/inhibitbutton.h new file mode 100644 index 00000000..02e362c5 --- /dev/null +++ b/src/widgets/inhibitbutton.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef INHIBITBUTTON_H +#define INHIBITBUTTON_H + +#include +#include + +class QLabel; +class InhibitButton : public QWidget +{ + Q_OBJECT +public: + enum State { + Enter = 0X0, + Leave = 0x1, + Press = 0x2, + Release = 0x4 + }; + InhibitButton(QWidget *parent); + ~InhibitButton(); + + void setText(const QString &text); + QString text(); + void setNormalPixmap(const QPixmap &normalPixmap); + QPixmap normalPixmap(); + void setHoverPixmap(const QPixmap &hoverPixmap); + QPixmap hoverPixmap(); + void setState(State state); + void setSelected(bool isSelected); + bool isSelected() { return m_isSelected; } + +Q_SIGNALS: + void clicked(); + void mouseEnter(); + void mouseLeave(); + +protected: +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *e) override; +#else + void enterEvent(QEvent *e) override; +#endif + void leaveEvent(QEvent *event) override; + void paintEvent(QPaintEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void showEvent(QShowEvent *event) override; + +private: + bool m_isSelected; + State m_state; + QLabel *m_iconLabel; + QLabel *m_textLabel; + QPixmap m_normalPixmap; + QPixmap m_hoverPixmap; +}; + +#endif // INHIBITBUTTON_H diff --git a/src/widgets/inhibitwarnview.cpp b/src/widgets/inhibitwarnview.cpp index 227b93c8..777da507 100644 --- a/src/widgets/inhibitwarnview.cpp +++ b/src/widgets/inhibitwarnview.cpp @@ -1,48 +1,44 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "inhibitwarnview.h" -#include "framedatabind.h" + +#include +#include +#include +#include +#include + +#ifdef ENABLE_DSS_SNIPE +#include +#include +#include +#endif #include -#include -const int ButtonIconSize = 28; +DWIDGET_USE_NAMESPACE + +#ifdef ENABLE_DSS_SNIPE +#define AMDBUS_SERVICE "org.desktopspec.ApplicationManager1" +#define AMDBUS_PATH_APP_PREFIX "/org/desktopspec/ApplicationManager1" +#define AMDBUS_APP_INTERFACE "org.desktopspec.ApplicationManager1.Application" +#endif + const int ButtonWidth = 200; const int ButtonHeight = 64; +const int FIXED_INHIBITOR_WIDTH = 328; +const QSize iconSize = QSize(24, 24); InhibitorRow::InhibitorRow(const QString &who, const QString &why, const QIcon &icon, QWidget *parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout; - QLabel *whoLabel = new QLabel(who); - QLabel *whyLabel = new QLabel("-" + why); - whoLabel->setStyleSheet("color: white; font: bold 12px;"); - whyLabel->setStyleSheet("color: white;"); + DLabel *whoLabel = new DLabel(who); + whoLabel->setElideMode(Qt::ElideRight); - layout->addStretch(); + DToolTip::setToolTipShowMode(whoLabel, DToolTip::ShowWhenElided); if (!icon.isNull()) { QLabel *iconLabel = new QLabel(this); @@ -53,10 +49,8 @@ InhibitorRow::InhibitorRow(const QString &who, const QString &why, const QIcon & } layout->addWidget(whoLabel); - layout->addWidget(whyLabel); layout->addStretch(); this->setFixedHeight(ButtonHeight); - this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); this->setLayout(layout); } @@ -79,63 +73,18 @@ void InhibitorRow::paintEvent(QPaintEvent *event) InhibitWarnView::InhibitWarnView(SessionBaseModel::PowerAction inhibitType, QWidget *parent) : WarningView(parent) , m_inhibitType(inhibitType) + , m_acceptBtn(new InhibitButton(this)) + , m_cancelBtn(new InhibitButton(this)) + , m_bottomWidget(new QWidget(this)) + , m_showDelay(false) { - m_acceptBtn = new QPushButton(QString()); - m_acceptBtn->setObjectName("AcceptButton"); - m_acceptBtn->setIconSize(QSize(ButtonIconSize, ButtonIconSize)); - m_acceptBtn->setFixedSize(ButtonWidth, ButtonHeight); - m_acceptBtn->setCheckable(true); - m_acceptBtn->setAutoExclusive(true); - m_acceptBtn->setFocusPolicy(Qt::NoFocus); - - m_cancelBtn = new QPushButton(tr("Cancel"), this); - m_cancelBtn->setObjectName("CancelButton"); - m_cancelBtn->setIconSize(QSize(ButtonIconSize, ButtonIconSize)); - m_cancelBtn->setFixedSize(ButtonWidth, ButtonHeight); - m_cancelBtn->setCheckable(true); - m_cancelBtn->setAutoExclusive(true); - m_cancelBtn->setFocusPolicy(Qt::NoFocus); - - const auto ratio = devicePixelRatioF(); - QIcon icon_pix = QIcon::fromTheme(":/img/cancel_normal.svg").pixmap(m_cancelBtn->iconSize() * ratio); - m_cancelBtn->setIcon(icon_pix); - - m_confirmTextLabel = new QLabel; - - m_inhibitorListLayout = new QVBoxLayout; - - std::function buttonChanged = std::bind(&InhibitWarnView::onOtherPageDataChanged, this, std::placeholders::_1); - m_dataBindIndex = FrameDataBind::Instance()->registerFunction("InhibitWarnView", buttonChanged); - - m_confirmTextLabel->setText("The reason of inhibit."); - m_confirmTextLabel->setAlignment(Qt::AlignCenter); - m_confirmTextLabel->setStyleSheet("color:white;"); - - QVBoxLayout *centralLayout = new QVBoxLayout; - centralLayout->addStretch(); - centralLayout->addLayout(m_inhibitorListLayout); - centralLayout->addSpacing(20); - centralLayout->addWidget(m_confirmTextLabel); - centralLayout->addSpacing(20); - centralLayout->addWidget(m_cancelBtn, 0, Qt::AlignHCenter); - centralLayout->addSpacing(20); - centralLayout->addWidget(m_acceptBtn, 0, Qt::AlignHCenter); - centralLayout->addStretch(); - - setLayout(centralLayout); - - m_cancelBtn->setChecked(true); - m_currentBtn = m_cancelBtn; - - updateIcon(); - - connect(m_cancelBtn, &QPushButton::clicked, this, &InhibitWarnView::cancelled); - connect(m_acceptBtn, &QPushButton::clicked, this, &InhibitWarnView::actionInvoked, Qt::QueuedConnection); + initUi(); + initConnection(); } InhibitWarnView::~InhibitWarnView() { - FrameDataBind::Instance()->unRegisterFunction("InhibitWarnView", m_dataBindIndex); + } void InhibitWarnView::setInhibitorList(const QList &list) @@ -149,12 +98,41 @@ void InhibitWarnView::setInhibitorList(const QList &list) for (const InhibitorData &inhibitor : list) { QIcon icon; - if (inhibitor.icon.isEmpty() && inhibitor.pid) { - QFileInfo executable_info(QFile::readLink(QString("/proc/%1/exe").arg(inhibitor.pid))); - - if (executable_info.exists()) { - icon = QIcon::fromTheme(executable_info.fileName()); + if (inhibitor.icon.isEmpty()) { + QString iconName; +#ifdef ENABLE_DSS_SNIPE + do { + const auto appId = Dtk::Core::DSGApplication::getId(inhibitor.pid); + if (appId.isEmpty()) + break; + const auto amDBusAppPath = QString("%1/%2").arg(AMDBUS_PATH_APP_PREFIX, DUtil::escapeToObjectPath(appId)); + QDBusReply reply = DDBusSender() + .service(AMDBUS_SERVICE) + .path(amDBusAppPath) + .interface(AMDBUS_APP_INTERFACE) + .property("Icons") + .get(); + if (reply.isValid()) { + auto ret = qdbus_cast>(reply.value().variant()); + iconName = ret.value("Desktop Entry"); + } else { + qCWarning(DDE_SHELL) << "Get icon error:" << reply.error().message(); + break; + } + } while(0); +#endif + + if (iconName.isEmpty() && inhibitor.pid) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QFileInfo executable_info(QFile::symLinkTarget(QString("/proc/%1/exe").arg(inhibitor.pid))); +#else + QFileInfo executable_info(QFile::readLink(QString("/proc/%1/exe").arg(inhibitor.pid))); +#endif + // 玲珑应用的exe指向的路径是容器内的路径,在容器外无法访问,因此不能判断文件是否存在 + QString iconName = executable_info.fileName(); } + + icon = QIcon::fromTheme(iconName); } else { icon = QIcon::fromTheme(inhibitor.icon, QIcon::fromTheme("application-x-desktop")); } @@ -166,13 +144,28 @@ void InhibitWarnView::setInhibitorList(const QList &list) QWidget *inhibitorWidget = new InhibitorRow(inhibitor.who, inhibitor.why, icon, this); m_inhibitorPtrList.append(inhibitorWidget); - m_inhibitorListLayout->addWidget(inhibitorWidget, 0, Qt::AlignHCenter); + m_inhibitorListLayout->addWidget(inhibitorWidget); } } -void InhibitWarnView::setInhibitConfirmMessage(const QString &text) +void InhibitWarnView::setInhibitConfirmMessage(const QString &text, bool showLoading) { m_confirmTextLabel->setText(text); + + if (showLoading && m_loading->width() != m_loading->height()) + m_loading->setFixedWidth(m_loading->height()); + m_loading->setVisible(showLoading); + showLoading ? m_loading->start() : m_loading->stop(); +} + +void InhibitWarnView::setDelayView(bool showDelay) +{ + m_showDelay = showDelay; +} + +bool InhibitWarnView::delayView() const +{ + return m_showDelay; } void InhibitWarnView::setAcceptReason(const QString &reason) @@ -180,109 +173,152 @@ void InhibitWarnView::setAcceptReason(const QString &reason) m_acceptBtn->setText(reason); } -void InhibitWarnView::updateIcon() +void InhibitWarnView::setAcceptVisible(const bool acceptable) +{ + m_acceptBtn->setVisible(acceptable); +} + +bool InhibitWarnView::hasInhibit() const +{ + return !m_inhibitorPtrList.isEmpty(); +} + +QString InhibitWarnView::iconString() { QString icon_string; switch (m_inhibitType) { case SessionBaseModel::PowerAction::RequireShutdown: - icon_string = ":/img/poweroff_warning_normal.svg"; + case SessionBaseModel::PowerAction::RequireUpdateShutdown: + icon_string = ":/img/inhibitview/poweroff_warning.svg"; break; case SessionBaseModel::PowerAction::RequireLogout: - icon_string = ":/img/logout_warning_normal.svg"; + icon_string = ":/img/inhibitview/logout_warning.svg"; break; default: - icon_string = ":/img/reboot_warning_normal.svg"; + icon_string = ":/img/inhibitview/reboot_warning.svg"; break; } - - const auto ratio = devicePixelRatioF(); - QIcon icon_pix = QIcon::fromTheme(icon_string).pixmap(m_acceptBtn->iconSize() * ratio); - m_acceptBtn->setIcon(icon_pix); + return icon_string; } -void InhibitWarnView::setAcceptVisible(const bool acceptable) +bool InhibitWarnView::focusNextPrevChild(bool next) { - m_acceptBtn->setVisible(acceptable); + if (!next) { + qCWarning(DDE_SHELL) << "Focus handling error, next prevent child is false"; + return WarningView::focusNextPrevChild(next); + } + + return WarningView::focusNextPrevChild(next); } -void InhibitWarnView::toggleButtonState() +void InhibitWarnView::keyPressEvent(QKeyEvent *event) { - if (m_cancelBtn->isChecked() && m_acceptBtn->isVisible()) - setCurrentButton(ButtonType::Accept); - else - setCurrentButton(ButtonType::Cancel); + // 如果DSpinner正在播放,此时用户按下的esc键,DSpinner将会停止播放,因此在这里直接返回 + if (m_loading->isPlaying() && event->key() == Qt::Key_Escape) + return; + + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down || event->key() == Qt::Key_Tab) { + QWidget *currentFocusWidget = focusWidget(); + QWidget *nextFocusWidget = nullptr; + + if (currentFocusWidget == m_cancelBtn) { + nextFocusWidget = m_acceptBtn; + } else if (currentFocusWidget == m_acceptBtn) { + nextFocusWidget = m_cancelBtn; + } - FrameDataBind::Instance()->updateValue("InhibitWarnView", m_currentBtn->objectName()); -} + if (nextFocusWidget) { + nextFocusWidget->setFocus(); + } else { + m_cancelBtn->setFocus(); + } + } -void InhibitWarnView::buttonClickHandle() -{ - emit m_currentBtn->clicked(); + QWidget::keyPressEvent(event); } -SessionBaseModel::PowerAction InhibitWarnView::inhibitType() const +void InhibitWarnView::initUi() { - return m_inhibitType; -} + QIcon acceptIcon = QIcon::fromTheme(iconString()); -bool InhibitWarnView::focusNextPrevChild(bool next) -{ - if (!next) { - qWarning() << "focus handling error, nextPrevChild is False"; - return WarningView::focusNextPrevChild(next); - } + m_acceptBtn->setObjectName("AcceptButton"); + m_acceptBtn->setFixedSize(ButtonWidth, ButtonHeight); + m_acceptBtn->setFocusPolicy(Qt::StrongFocus); + m_acceptBtn->setNormalPixmap(acceptIcon.pixmap(iconSize)); + m_acceptBtn->setHoverPixmap(acceptIcon.pixmap(iconSize)); - if (m_acceptBtn->hasFocus() && m_acceptBtn->isVisible()) - setCurrentButton(ButtonType::Cancel); - else - setCurrentButton(ButtonType::Accept); + QIcon iconCancelNormal = QIcon::fromTheme(":/img/inhibitview/cancel_normal.svg"); + QIcon iconCancelHover = QIcon::fromTheme(":/img/inhibitview/cancel_hover.svg"); - FrameDataBind::Instance()->updateValue("InhibitWarnView", m_currentBtn->objectName()); + m_cancelBtn->setNormalPixmap(iconCancelNormal.pixmap(iconSize)); + m_cancelBtn->setHoverPixmap(iconCancelHover.pixmap(iconSize)); - return WarningView::focusNextPrevChild(next); -} + m_cancelBtn->setObjectName("CancelButton"); + m_cancelBtn->setFixedSize(ButtonWidth, ButtonHeight); + m_cancelBtn->setText(tr("Cancel")); + m_cancelBtn->setFocusPolicy(Qt::StrongFocus); + + auto inhibitorListWidget = new QWidget(this); + inhibitorListWidget->setFixedWidth(FIXED_INHIBITOR_WIDTH); + m_inhibitorListLayout = new QVBoxLayout(inhibitorListWidget); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_inhibitorListLayout->setContentsMargins(0, 0, 0, 0); +#else + m_inhibitorListLayout->setMargin(0); +#endif + m_inhibitorListLayout->setSpacing(10); + QVBoxLayout *buttonLayout = new QVBoxLayout(m_bottomWidget); + buttonLayout->setAlignment(Qt::AlignBottom); + + QWidget *textWidget = new QWidget(m_bottomWidget); + QHBoxLayout *textLayout = new QHBoxLayout(textWidget); + textLayout->setContentsMargins(0, 0, 0, 0); + textLayout->setSpacing(10); + m_loading = new Dtk::Widget::DSpinner(textWidget); + m_confirmTextLabel = new QLabel(textWidget); + m_confirmTextLabel->setText(tr("The reason of inhibit.")); + m_confirmTextLabel->setAlignment(Qt::AlignCenter); -void InhibitWarnView::setCurrentButton(const ButtonType btntype) -{ - switch (btntype) { - case ButtonType::Cancel: - m_acceptBtn->setChecked(false); - m_cancelBtn->setChecked(true); - m_currentBtn = m_cancelBtn; - break; + DFontSizeManager::instance()->bind(m_confirmTextLabel, DFontSizeManager::T5); + textLayout->addStretch(); + textLayout->addWidget(m_loading); + textLayout->addWidget(m_confirmTextLabel); + textLayout->addStretch(); - case ButtonType::Accept: - m_cancelBtn->setChecked(false); - m_acceptBtn->setChecked(true); - m_currentBtn = m_acceptBtn; - break; - } + QVBoxLayout *centralLayout = new QVBoxLayout; + centralLayout->addStretch(); + + centralLayout->addWidget(inhibitorListWidget, 0, Qt::AlignHCenter); + centralLayout->addSpacing(50); + centralLayout->addWidget(m_bottomWidget); + centralLayout->addStretch(); + setLayout(centralLayout); + + buttonLayout->addWidget(textWidget); + buttonLayout->addSpacing(70); + buttonLayout->addWidget(m_cancelBtn, 0, Qt::AlignHCenter); + buttonLayout->addSpacing(15); + buttonLayout->addWidget(m_acceptBtn, 0, Qt::AlignHCenter); + + setFocusPolicy(Qt::ClickFocus); + m_loading->hide(); } -void InhibitWarnView::onOtherPageDataChanged(const QVariant &value) +void InhibitWarnView::initConnection() { - const QString objectName { value.toString() }; - - if (objectName == "AcceptButton") - setCurrentButton(ButtonType::Accept); - else - setCurrentButton(ButtonType::Cancel); + connect(m_cancelBtn, &InhibitButton::clicked, this, &InhibitWarnView::cancelled); + connect(m_acceptBtn, &InhibitButton::clicked, this, &InhibitWarnView::onAccept); } -void InhibitWarnView::keyPressEvent(QKeyEvent *event) +void InhibitWarnView::onAccept() { - switch (event->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - toggleButtonState(); - break; - case Qt::Key_Return: - m_currentBtn->clicked(); - break; - case Qt::Key_Enter: - m_currentBtn->clicked(); - break; + if (!m_inhibitorPtrList.isEmpty()) { + int height = m_bottomWidget->height(); + m_cancelBtn->hide(); + m_acceptBtn->hide(); + m_bottomWidget->setFixedHeight(height); + static_cast(m_bottomWidget->layout())->addStretch(); } - QWidget::keyPressEvent(event); + + emit actionInvoked(); } diff --git a/src/widgets/inhibitwarnview.h b/src/widgets/inhibitwarnview.h index 869ec268..a7c0ae05 100644 --- a/src/widgets/inhibitwarnview.h +++ b/src/widgets/inhibitwarnview.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef INHIBITWARNVIEW_H #define INHIBITWARNVIEW_H @@ -29,10 +8,16 @@ #include "warningview.h" #include "rounditembutton.h" #include "sessionbasemodel.h" +#include "inhibitbutton.h" #include -class QPushButton; +namespace Dtk { +namespace Widget { +class DSpinner; +} +} + class InhibitorRow : public QWidget { Q_OBJECT @@ -61,37 +46,40 @@ class InhibitWarnView : public WarningView }; void setInhibitorList(const QList & list); - void setInhibitConfirmMessage(const QString &text); + void setInhibitConfirmMessage(const QString &text, bool showLoading = false); + void setDelayView(bool showDelay); + bool delayView() const; void setAcceptReason(const QString &reason) override; void setAcceptVisible(const bool acceptable); - - void toggleButtonState() Q_DECL_OVERRIDE; - void buttonClickHandle() Q_DECL_OVERRIDE; - - SessionBaseModel::PowerAction inhibitType() const; - -protected: - void updateIcon(); - bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE; - void setCurrentButton(const ButtonType btntype) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *event) override; + bool hasInhibit() const; signals: void cancelled() const; void actionInvoked() const; +protected: + QString iconString(); + bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + private: - void onOtherPageDataChanged(const QVariant &value); + void initUi(); + void initConnection(); + +private slots: + void onAccept(); private: SessionBaseModel::PowerAction m_inhibitType; QList m_inhibitorPtrList; QVBoxLayout *m_inhibitorListLayout = nullptr; + Dtk::Widget::DSpinner *m_loading; QLabel *m_confirmTextLabel = nullptr; - QPushButton *m_acceptBtn; - QPushButton *m_cancelBtn; - QPushButton *m_currentBtn; + InhibitButton *m_acceptBtn; + InhibitButton *m_cancelBtn; + QWidget *m_bottomWidget; int m_dataBindIndex; + bool m_showDelay; }; #endif // INHIBITWARNVIEW_H diff --git a/src/widgets/kblayoutlistview.cpp b/src/widgets/kblayoutlistview.cpp index d6721590..ec0bff90 100644 --- a/src/widgets/kblayoutlistview.cpp +++ b/src/widgets/kblayoutlistview.cpp @@ -1,27 +1,7 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "kblayoutlistview.h" #include @@ -57,7 +37,7 @@ void KBLayoutListView::initData(const QStringList &buttons) m_buttonModel->clear(); - resize(width(), DDESESSIONCC::LAYOUTBUTTON_HEIGHT * m_kbdParseList.count()); + resize(width(), DDESESSIONCC::LAYOUT_BUTTON_HEIGHT * m_kbdParseList.count()); for (int i = 0; i < m_kbdParseList.size(); i++) addItem(m_kbdParseList[i]); @@ -80,6 +60,8 @@ void KBLayoutListView::initUI() setViewportMargins(0, 0, 0, 0); setItemSpacing(0); setItemSize(QSize(200, 34)); + setBackgroundType(DStyledItemDelegate::BackgroundType::ClipCornerBackground); + setSelectionMode(QAbstractItemView::NoSelection); QMargins itemMargins(this->itemMargins()); itemMargins.setLeft(8); @@ -101,7 +83,11 @@ void KBLayoutListView::updateSelectState(const QString &name) continue; } - QIcon icon = qobject_cast(style())->standardIcon(DStyle::SP_MarkElement); + QIcon icon; + DStyle *style_ptr = qobject_cast(style()); + if (style_ptr) { + icon = style_ptr->standardIcon(DStyle::SP_MarkElement); + } action->setIcon(icon); setCurrentIndex(item->index()); update(item->index()); @@ -143,19 +129,14 @@ void KBLayoutListView::addItem(const QString &name) QSize iconSize(12, 10); auto leftAction = new DViewItemAction(Qt::AlignVCenter, iconSize, iconSize, true); QIcon icon; - if (name != m_curLanguage) { - icon = QIcon(); - } else { - icon = qobject_cast(style())->standardIcon(DStyle::SP_MarkElement); + if (name == m_curLanguage) { + DStyle *style_ptr = qobject_cast(style()); + if (style_ptr) { + icon = style_ptr->standardIcon(DStyle::SP_MarkElement); + } } leftAction->setIcon(icon); item->setActionList(Qt::Edge::LeftEdge, { leftAction }); m_buttonModel->appendRow(item); } - -void KBLayoutListView::resizeEvent(QResizeEvent *event) -{ - emit sizeChange(); - DListView::resizeEvent(event); -} diff --git a/src/widgets/kblayoutlistview.h b/src/widgets/kblayoutlistview.h index 1ec49161..59117964 100644 --- a/src/widgets/kblayoutlistview.h +++ b/src/widgets/kblayoutlistview.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef KBLAYOUTLISTVIEW #define KBLAYOUTLISTVIEW @@ -47,7 +26,6 @@ class KBLayoutListView: public DListView signals: void itemClicked(const QString &str); - void sizeChange(); public slots: void onItemClick(const QModelIndex &index); @@ -56,7 +34,6 @@ public slots: void initUI(); void updateSelectState(const QString &name); void addItem(const QString &name); - void resizeEvent(QResizeEvent *event) override; private: QStringList m_buttons; diff --git a/src/widgets/logowidget.cpp b/src/widgets/logowidget.cpp index 8fdafae0..51829953 100644 --- a/src/widgets/logowidget.cpp +++ b/src/widgets/logowidget.cpp @@ -1,41 +1,18 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later -#include -#include -#include #include -#include -#include -#include + #include "public_func.h" #include "util_updateui.h" #include "logowidget.h" +#include "dconfig_helper.h" +#include "constants.h" DCORE_USE_NAMESPACE +using namespace DDESESSIONCC; #define PIXMAP_WIDTH 128 #define PIXMAP_HEIGHT 132 /* SessionBaseWindow */ @@ -49,7 +26,9 @@ LogoWidget::LogoWidget(QWidget *parent) : QFrame(parent) , m_logoLabel(new QLabel(this)) , m_logoVersionLabel(new DLabel(this)) + , m_customLogoLabel(nullptr) { + setMinimumHeight(PIXMAP_HEIGHT); setObjectName("LogoWidget"); m_logoLabel->setAccessibleName("LogoLabel"); //设置QSizePolicy为固定高度,以保证右边版本号内容顶部能和图片对齐 @@ -75,6 +54,9 @@ void LogoWidget::initUI() m_logoLabel->setPixmap(pixmap); logoLayout->addWidget(m_logoLabel, 0, Qt::AlignBottom | Qt::AlignLeft); + // custom log + loadCustomLogo(); + /* version */ m_logoVersionLabel->setObjectName("LogoVersion"); //设置版本号显示部件自动拉伸,以保证高度和图标高度一致 @@ -103,6 +85,11 @@ void LogoWidget::initUI() logoLayout->addWidget(m_logoVersionLabel); updateStyle(":/skin/login.qss", m_logoVersionLabel); + m_logoVersionLabel->setVisible(DConfigHelper::instance()->getConfig(SHOW_SYSTEM_VERSION, true).toBool()); + + DConfigHelper::instance()->bind(this, SHOW_SYSTEM_VERSION, &LogoWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, CUSTOM_LOGO_PATH, &LogoWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, CUSTOM_LOGO_POS, &LogoWidget::onDConfigPropertyChanged); } QPixmap LogoWidget::loadSystemLogo() @@ -118,7 +105,7 @@ QString LogoWidget::getVersion() if (DSysInfo::uosType() == DSysInfo::UosServer) { version = QString("%1").arg(DSysInfo::majorVersion()); } else if (DSysInfo::isDeepin()) { - version = QString("%1 %2").arg(DSysInfo::majorVersion()).arg(DSysInfo::uosEditionName(m_locale)); + version = QString("%1 %2").arg(DSysInfo::majorVersion()).arg(DSysInfo::uosEditionName(QLocale(m_locale))); } else { version = QString("%1 %2").arg(DSysInfo::productVersion()).arg(DSysInfo::productTypeString()); } @@ -133,6 +120,9 @@ QString LogoWidget::getVersion() void LogoWidget::updateLocale(const QString &locale) { m_locale = locale; + if(DSysInfo::UosEdition::UosEducation == DSysInfo::uosEditionType()) { //教育版登录界面不要显示系统版本号(和Logo冲突) + return; + } m_logoVersionLabel->setText(getVersion()); } @@ -147,4 +137,62 @@ void LogoWidget::resizeEvent(QResizeEvent *event) QFont font(m_logoVersionLabel->font()); font.setPixelSize(m_logoLabel->height() / 2); m_logoVersionLabel->setFont(font); + + updateCustomLogoPos(); +} + +void LogoWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == SHOW_SYSTEM_VERSION) { + obj->m_logoVersionLabel->setVisible(value.toBool()); + } else if (key == CUSTOM_LOGO_PATH) { + obj->loadCustomLogo(); + obj->updateCustomLogoPos(); + } else if (key == CUSTOM_LOGO_POS) { + obj->updateCustomLogoPos(); + } +} + +void LogoWidget::loadCustomLogo() +{ + QString path = DConfigHelper::instance()->getConfig(CUSTOM_LOGO_PATH, "").toString(); + QFile file(path); + if (path.isEmpty() || !file.exists() || file.size() > 500 * 1024) { + if (m_customLogoLabel) { + m_customLogoLabel->setPixmap(QPixmap()); + } + return; + } + + QPixmap pixmap = loadPixmap(path,QSize()); + if (pixmap.width() > this->rect().width() / 2 || pixmap.height() > PIXMAP_HEIGHT) { + pixmap = loadPixmap(path,QSize(PIXMAP_WIDTH, PIXMAP_HEIGHT)); + } + + if (m_customLogoLabel == nullptr) { + m_customLogoLabel = new QLabel(this); + m_customLogoLabel->setObjectName("custom_Logo"); + m_customLogoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + } + + m_customLogoLabel->setPixmap(pixmap); + m_customLogoLabel->resize(m_customLogoLabel->sizeHint()); +} + +void LogoWidget::updateCustomLogoPos() +{ + if (!m_customLogoLabel) { + return; + } + QStringList pos = DConfigHelper::instance()->getConfig(CUSTOM_LOGO_POS, "0,0").toString().split(','); + if (pos.size() < 2) { + pos = QStringList({"0","0"}); + } + + QRect rect = m_logoLabel->geometry(); + m_customLogoLabel->move(rect.x() + rect.width() + pos[0].toInt() , rect.y() - pos[1].toInt() + rect.height() - m_customLogoLabel->height()); } diff --git a/src/widgets/logowidget.h b/src/widgets/logowidget.h index 87ab23a7..709e49f8 100644 --- a/src/widgets/logowidget.h +++ b/src/widgets/logowidget.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef LOGOWIDGET #define LOGOWIDGET @@ -41,6 +20,7 @@ class LogoWidget : public QFrame ~LogoWidget() override; void updateLocale(const QString &locale); + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject* objPtr); protected: void resizeEvent(QResizeEvent *event) override; @@ -48,11 +28,16 @@ class LogoWidget : public QFrame private: void initUI(); QPixmap loadSystemLogo(); + void loadCustomLogo(); QString getVersion(); + void updateCustomLogoPos(); private: QLabel *m_logoLabel; DLabel *m_logoVersionLabel; QString m_locale; + + // 第三方logo配置控制显示 + QLabel *m_customLogoLabel; }; #endif // LOGOFRAME diff --git a/src/widgets/mediawidget.cpp b/src/widgets/mediawidget.cpp index 11c67fd5..fa533f16 100644 --- a/src/widgets/mediawidget.cpp +++ b/src/widgets/mediawidget.cpp @@ -1,54 +1,39 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "mediawidget.h" #include "util_updateui.h" +#include "constants.h" +#include "dbusmediaplayer2.h" + #include -#include #include MediaWidget::MediaWidget(QWidget *parent) : QWidget(parent) + , m_dmprisWidget(nullptr) { - initUI(); - initConnect(); } void MediaWidget::initUI() { + if (m_dmprisWidget) + return; m_dmprisWidget = new DMPRISControl; m_dmprisWidget->setAccessibleName("MPRISWidget"); - m_dmprisWidget->setFixedWidth(200); + m_dmprisWidget->setFixedHeight(DDESESSIONCC::LOCK_CONTENT_TOP_WIDGET_HEIGHT); m_dmprisWidget->setPictureVisible(false); - QHBoxLayout *mainlayout = new QHBoxLayout; - - mainlayout->addWidget(m_dmprisWidget, 0, Qt::AlignBottom); + auto mainLayout = new QVBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + mainLayout->setContentsMargins(0, 0, 0, 0); +#else + mainLayout->setMargin(0); +#endif + mainLayout->addWidget(m_dmprisWidget); + setLayout(mainLayout); - setLayout(mainlayout); - - //updateStyle(":/skin/mediawidget.qss", this); + initConnect(); } void MediaWidget::initConnect() @@ -65,11 +50,9 @@ void MediaWidget::initMediaPlayer() QDBusPendingCall call = dbusInter.asyncCall("ListNames"); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); - connect(watcher, &QDBusPendingCallWatcher::finished, [ = ] { + connect(watcher, &QDBusPendingCallWatcher::finished, [=] { if (!call.isError()) { QDBusReply reply = call.reply(); - //qDebug() << "one key Login User Name is : " << reply.value(); - const QStringList &serviceList = reply.value(); QString service = QString(); for (const QString &serv : serviceList) { @@ -79,8 +62,8 @@ void MediaWidget::initMediaPlayer() service = serv; break; } + if (service.isEmpty()) { - qDebug() << "media player dbus has not started, waiting for signal..."; QDBusConnectionInterface *dbusDaemonInterface = QDBusConnection::sessionBus().interface(); connect(dbusDaemonInterface, &QDBusConnectionInterface::serviceOwnerChanged, this, [=](const QString &name, const QString &oldOwner, const QString &newOwner) { @@ -93,15 +76,15 @@ void MediaWidget::initMediaPlayer() return; } - qDebug() << "got media player dbus service: " << service; - - m_dbusInter = new DBusMediaPlayer2(service, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this); - - m_dbusInter->MetadataChanged(); - m_dbusInter->PlaybackStatusChanged(); - m_dbusInter->VolumeChanged(); + qCDebug(DDE_SHELL) << "Got media player DBus service:" << service; + initUI(); + auto dbusInter = new DBusMediaPlayer2(service, "/org/mpris/MediaPlayer2", QDBusConnection::sessionBus(), this); + dbusInter->MetadataChanged(); + dbusInter->PlaybackStatusChanged(); + dbusInter->VolumeChanged(); + dbusInter->deleteLater(); } else { - qWarning() << "init media player error: " << call.error().message(); + qCWarning(DDE_SHELL) << "Init media player error: " << call.error().message(); } watcher->deleteLater(); @@ -110,6 +93,5 @@ void MediaWidget::initMediaPlayer() void MediaWidget::changeVisible() { - const bool isWorking = m_dmprisWidget->isWorking(); - m_dmprisWidget->setVisible(isWorking); + m_dmprisWidget->setVisible(m_dmprisWidget->isWorking()); } diff --git a/src/widgets/mediawidget.h b/src/widgets/mediawidget.h index e2763ea5..c600e41a 100644 --- a/src/widgets/mediawidget.h +++ b/src/widgets/mediawidget.h @@ -1,36 +1,13 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef MEDIAWIDGET_H #define MEDIAWIDGET_H -#include "dbusmediaplayer2.h" +#include #include -#include -#include DWIDGET_USE_NAMESPACE @@ -50,7 +27,6 @@ private slots: private: DMPRISControl *m_dmprisWidget; - DBusMediaPlayer2 *m_dbusInter; }; #endif // MEDIAWIDGET_H diff --git a/src/widgets/multiuserswarningview.cpp b/src/widgets/multiuserswarningview.cpp index 702c7e45..9a492600 100644 --- a/src/widgets/multiuserswarningview.cpp +++ b/src/widgets/multiuserswarningview.cpp @@ -1,63 +1,49 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "multiuserswarningview.h" +#include "inhibitbutton.h" + +#include #include #include -#include -#include #include #include #include #include +#include const static QSize UserAvatarSize = QSize(64, 64); const static QSize UserListItemSize = QSize(180, 80); +const int ButtonWidth = 200; +const int ButtonHeight = 64; +const QSize iconSize = QSize(24, 24); MultiUsersWarningView::MultiUsersWarningView(SessionBaseModel::PowerAction inhibitType, QWidget *parent) : WarningView(parent) , m_vLayout(new QVBoxLayout(this)) , m_userList(new QListWidget) , m_warningTip(new QLabel) - , m_cancelBtn(new QPushButton(tr("Cancel"))) - , m_actionBtn(new QPushButton(QString())) - , m_currentBtn(nullptr) + , m_cancelBtn(new InhibitButton(this)) + , m_actionBtn(new InhibitButton(this)) , m_inhibitType(inhibitType) { + QIcon acceptIcon = QIcon::fromTheme(iconString()); + m_userList->setAttribute(Qt::WA_TranslucentBackground); -// m_userList->setSelectionRectVisible(false); + // m_userList->setSelectionRectVisible(false); m_userList->setSelectionMode(QListView::NoSelection); m_userList->setEditTriggers(QListView::NoEditTriggers); m_userList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_userList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); -// m_userList->viewport()->setAttribute(Qt::WA_TranslucentBackground); + // m_userList->viewport()->setAttribute(Qt::WA_TranslucentBackground); m_userList->setFrameStyle(QFrame::NoFrame); m_userList->setGridSize(UserListItemSize); m_userList->setFocusPolicy(Qt::NoFocus); m_userList->setStyleSheet("background-color:transparent;"); + DFontSizeManager::instance()->bind(m_warningTip, DFontSizeManager::T5); m_warningTip->setFixedWidth(300); m_warningTip->setStyleSheet("color: white;"); @@ -66,38 +52,39 @@ MultiUsersWarningView::MultiUsersWarningView(SessionBaseModel::PowerAction inhib m_warningTip->setFocusPolicy(Qt::NoFocus); m_warningTip->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_actionBtn->setIconSize(QSize(m_buttonIconSize, m_buttonIconSize)); - m_actionBtn->setFixedSize(m_buttonWidth, m_buttonHeight); - m_cancelBtn->setIconSize(QSize(m_buttonIconSize, m_buttonIconSize)); - m_cancelBtn->setFixedSize(m_buttonWidth, m_buttonHeight); + m_actionBtn->setFixedSize(ButtonWidth, ButtonHeight); + m_actionBtn->setFocusPolicy(Qt::StrongFocus); + m_actionBtn->setNormalPixmap(acceptIcon.pixmap(iconSize * devicePixelRatioF())); + m_actionBtn->setHoverPixmap(acceptIcon.pixmap(iconSize * devicePixelRatioF())); + QIcon iconCancelNormal = QIcon::fromTheme(":/img/inhibitview/cancel_normal.svg"); + QIcon iconCancelHover = QIcon::fromTheme(":/img/inhibitview/cancel_hover.svg"); - const auto ratio = devicePixelRatioF(); - QIcon icon_pix = QIcon::fromTheme(":/img/cancel_normal.svg").pixmap(m_cancelBtn->iconSize() * ratio); - m_cancelBtn->setIcon(icon_pix); + m_cancelBtn->setFixedSize(ButtonWidth, ButtonHeight); + m_cancelBtn->setFocusPolicy(Qt::StrongFocus); + m_cancelBtn->setNormalPixmap(iconCancelNormal.pixmap(iconSize * devicePixelRatioF())); + m_cancelBtn->setHoverPixmap(iconCancelHover.pixmap(iconSize * devicePixelRatioF())); + m_cancelBtn->setText(tr("Cancel")); QVBoxLayout *btnLayout = new QVBoxLayout; - btnLayout->addStretch(1); + btnLayout->addStretch(); btnLayout->addWidget(m_cancelBtn, 0, Qt::AlignHCenter); - btnLayout->addSpacing(20); + btnLayout->addSpacing(15); btnLayout->addWidget(m_actionBtn, 0, Qt::AlignHCenter); - btnLayout->addStretch(1); + btnLayout->addStretch(); m_vLayout->addStretch(); m_vLayout->addWidget(m_userList, 0, Qt::AlignHCenter); m_vLayout->addSpacing(40); m_vLayout->addWidget(m_warningTip, 1, Qt::AlignHCenter); - m_vLayout->addSpacing(40); m_vLayout->addLayout(btnLayout); m_vLayout->addStretch(); - m_cancelBtn->setCheckable(true); - m_cancelBtn->setChecked(true); - m_currentBtn = m_cancelBtn; + updateWarningTip(); - updateIcon(); + connect(m_cancelBtn, &InhibitButton::clicked, this, &MultiUsersWarningView::cancelled); + connect(m_actionBtn, &InhibitButton::clicked, this, &MultiUsersWarningView::actionInvoked); - connect(m_cancelBtn, &QPushButton::clicked, this, &MultiUsersWarningView::cancelled); - connect(m_actionBtn, &QPushButton::clicked, this, &MultiUsersWarningView::actionInvoked); + setFocusPolicy(Qt::ClickFocus); } MultiUsersWarningView::~MultiUsersWarningView() @@ -125,75 +112,50 @@ SessionBaseModel::PowerAction MultiUsersWarningView::action() const return m_action; } -void MultiUsersWarningView::updateIcon() +void MultiUsersWarningView::updateWarningTip() { - QString icon_string; switch (m_inhibitType) { case SessionBaseModel::PowerAction::RequireShutdown: - icon_string = ":/img/poweroff_warning_normal.svg"; m_warningTip->setText(tr("The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down?")); break; default: - icon_string = ":/img/reboot_warning_normal.svg"; m_warningTip->setText(tr("The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot?")); break; } - - const auto ratio = devicePixelRatioF(); - QIcon icon_pix = QIcon::fromTheme(icon_string).pixmap(m_actionBtn->iconSize() * ratio); - m_actionBtn->setIcon(icon_pix); } -void MultiUsersWarningView::toggleButtonState() -{ - if (m_actionBtn->isChecked()) - setCurrentButton(ButtonType::Cancel); - else - setCurrentButton(ButtonType::Accept); -} - -void MultiUsersWarningView::buttonClickHandle() +void MultiUsersWarningView::setAcceptReason(const QString &reason) { - emit m_currentBtn->clicked(); + m_actionBtn->setText(reason); } -void MultiUsersWarningView::setAcceptReason(const QString &reason) +QString MultiUsersWarningView::iconString() { - m_actionBtn->setText(reason); + QString icon_string; + switch (m_inhibitType) { + case SessionBaseModel::PowerAction::RequireShutdown: + case SessionBaseModel::PowerAction::RequireUpdateShutdown: + icon_string = ":/img/inhibitview/poweroff_warning.svg"; + break; + case SessionBaseModel::PowerAction::RequireLogout: + icon_string = ":/img/inhibitview/logout_warning.svg"; + break; + default: + icon_string = ":/img/inhibitview/reboot_warning.svg"; + break; + } + return icon_string; } bool MultiUsersWarningView::focusNextPrevChild(bool next) { if (!next) { - qWarning() << "focus handling error, nextPrevChild is False"; + qCWarning(DDE_SHELL) << "Focus handling error, next prevent child is false"; return WarningView::focusNextPrevChild(next); } - - if (m_actionBtn->hasFocus()) - setCurrentButton(ButtonType::Cancel); - else - setCurrentButton(ButtonType::Accept); - return WarningView::focusNextPrevChild(next); } -void MultiUsersWarningView::setCurrentButton(const ButtonType btntype) -{ - switch (btntype) { - case ButtonType::Cancel: - m_actionBtn->setChecked(false); - m_cancelBtn->setChecked(true); - m_currentBtn = m_cancelBtn; - break; - - case ButtonType::Accept: - m_cancelBtn->setChecked(false); - m_actionBtn->setChecked(true); - m_currentBtn = m_actionBtn; - break; - } -} - QString MultiUsersWarningView::getUserIcon(const QString &path) { const QUrl url(path); @@ -205,19 +167,23 @@ QString MultiUsersWarningView::getUserIcon(const QString &path) void MultiUsersWarningView::keyPressEvent(QKeyEvent *event) { - switch (event->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - toggleButtonState(); - break; - case Qt::Key_Return: - m_currentBtn->clicked(); - break; - case Qt::Key_Enter: - m_currentBtn->clicked(); - break; + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down || event->key() == Qt::Key_Tab) { + QWidget *currentFocusWidget = focusWidget(); + QWidget *nextFocusWidget = nullptr; + + if (currentFocusWidget == m_cancelBtn) { + nextFocusWidget = m_actionBtn; + } else if (currentFocusWidget == m_actionBtn) { + nextFocusWidget = m_cancelBtn; + } + + if (nextFocusWidget) { + nextFocusWidget->setFocus(); + } else { + m_cancelBtn->setFocus(); + } } + QWidget::keyPressEvent(event); } @@ -233,6 +199,7 @@ UserListItem::UserListItem(const QString &icon, const QString &name) : m_icon->setPixmap(getRoundPixmap(icon)); m_name->setStyleSheet("color: white;"); + DFontSizeManager::instance()->bind(m_name, DFontSizeManager::T5); m_name->move(80, 20); } diff --git a/src/widgets/multiuserswarningview.h b/src/widgets/multiuserswarningview.h index d7395559..d9c82923 100644 --- a/src/widgets/multiuserswarningview.h +++ b/src/widgets/multiuserswarningview.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef MULTIUSERSWARNINGVIEW_H #define MULTIUSERSWARNINGVIEW_H @@ -39,7 +18,7 @@ class QVBoxLayout; DWIDGET_USE_NAMESPACE -class QPushButton; +class InhibitButton; class MultiUsersWarningView : public WarningView { Q_OBJECT @@ -49,14 +28,12 @@ class MultiUsersWarningView : public WarningView void setUsers(QList> users); SessionBaseModel::PowerAction action() const; - void toggleButtonState() Q_DECL_OVERRIDE; - void buttonClickHandle() Q_DECL_OVERRIDE; void setAcceptReason(const QString &reason) Q_DECL_OVERRIDE; - void keyPressEvent(QKeyEvent *event)Q_DECL_OVERRIDE; protected: + QString iconString(); bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE; - void setCurrentButton(const ButtonType btntype) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; signals: void actionInvoked(); @@ -64,19 +41,15 @@ class MultiUsersWarningView : public WarningView private: QString getUserIcon(const QString &path); - void updateIcon(); + void updateWarningTip(); private: QVBoxLayout * m_vLayout; QListWidget * m_userList; QLabel * m_warningTip; - QPushButton * m_cancelBtn; - QPushButton * m_actionBtn; - QPushButton *m_currentBtn; + InhibitButton * m_cancelBtn; + InhibitButton * m_actionBtn; SessionBaseModel::PowerAction m_action; - const int m_buttonIconSize = 28; - const int m_buttonWidth = 200; - const int m_buttonHeight = 64; SessionBaseModel::PowerAction m_inhibitType; }; diff --git a/src/widgets/passworderrortipswidget.cpp b/src/widgets/passworderrortipswidget.cpp new file mode 100644 index 00000000..4469bd1d --- /dev/null +++ b/src/widgets/passworderrortipswidget.cpp @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + + +#include "passworderrortipswidget.h" + +#include + +#include "QVBoxLayout" +#include "QHBoxLayout" +#include "QEvent" +#include "QMouseEvent" + +#include "dpalette.h" +#include "dlabel.h" + +const int MaxWidth = 402; +const int MinWidth = 140; +const int MaxHeight = 154; + +PasswordErrorTipsWidget::PasswordErrorTipsWidget(QWidget *parent) + : QWidget(parent) + , m_tipLabel(new DLabel(this)) + , m_showMore(new DLabel(this)) + , m_detailTextEdit(new DTextEdit(this)) + , m_tipsWidget(new QWidget(this)) + , m_errorMsgNum(0) +{ + setAttribute(Qt::WA_TranslucentBackground); // 设置窗口背景透明 + setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip); + + initUi(); + + m_showMore->installEventFilter(this); + m_tipLabel->installEventFilter(this); +} + +void PasswordErrorTipsWidget::initUi() +{ + QVBoxLayout* mainLay = new QVBoxLayout(this); + mainLay->setContentsMargins(10, 5, 10, 5); + mainLay->setSpacing(0); + + QHBoxLayout* hlay = new QHBoxLayout(m_tipsWidget); + hlay->setContentsMargins(0, 0, 0, 0); + hlay->setSpacing(5); + hlay->addWidget(m_tipLabel, 0, Qt::AlignmentFlag::AlignLeft | Qt::AlignmentFlag::AlignTop); + DFontSizeManager::instance()->bind(m_tipLabel, DFontSizeManager::T6); + m_tipLabel->setForegroundRole(DPalette::TextWarning); + + QPixmap pixmap; + pixmap.load(":img/warning.svg"); + m_showMore->setPixmap(pixmap); + m_showMore->setVisible(false); + + hlay->addWidget(m_showMore, 0, Qt::AlignmentFlag::AlignCenter); + mainLay->addWidget(m_tipsWidget, 0, Qt::AlignmentFlag::AlignTop | Qt::AlignmentFlag::AlignLeft); + + m_detailTextEdit->hide(); + QFont detailFont; + detailFont.setFamily("Noto Sans CJK SC-Thin"); + detailFont.setWeight(QFont::ExtraLight); + QPalette palette = m_detailTextEdit->palette(); + palette.setColor(QPalette::WindowText, Qt::black); + m_detailTextEdit->setPalette(palette); + + DFontSizeManager::instance()->bind(m_detailTextEdit, DFontSizeManager::T6); + m_detailTextEdit->setAttribute(Qt::WA_TranslucentBackground, false); + m_detailTextEdit->setFixedWidth(MaxWidth); + m_detailTextEdit->setFont(detailFont); + m_detailTextEdit->setFrameShape(QFrame::Shape::NoFrame); + m_detailTextEdit->setReadOnly(true); + m_detailTextEdit->setTextInteractionFlags(Qt::NoTextInteraction); + m_detailTextEdit->setLineWrapMode(QTextEdit::LineWrapMode::WidgetWidth); + m_detailTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded); + m_detailTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); + m_detailTextEdit->setAttribute(Qt::WA_TranslucentBackground, true); + + mainLay->addWidget(m_detailTextEdit, 0, Qt::AlignmentFlag::AlignLeft); +} + +bool PasswordErrorTipsWidget::eventFilter(QObject *watch, QEvent *event) +{ + if (watch->isWidgetType() && event->type() == QEvent::MouseButtonPress + && (qobject_cast(watch) == m_tipLabel || qobject_cast(watch) == m_showMore)) { + QMouseEvent *mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) { + if (m_detailTextEdit->toPlainText().isEmpty()) { + return QObject::eventFilter(watch, event); + } + m_detailTextEdit->setText(m_detailTextEdit->toPlainText()); + m_detailTextEdit->setVisible(!m_detailTextEdit->isVisible()); + QSizeF docSize = m_detailTextEdit->textCursor().document()->size(); + int height = docSize.height() > MaxHeight ? MaxHeight : docSize.height(); + int width = 0; + if (docSize.width() <= MinWidth) { + width = MinWidth; + } else if (docSize.width() <= MaxWidth) { + width = docSize.width(); + } else { + width = MaxWidth; + } + m_detailTextEdit->setFixedSize(width, height); + adjustSize(); + } + } + return QObject::eventFilter(watch, event); +} + +void PasswordErrorTipsWidget::setErrDetailVisible(bool isVisible) +{ + m_detailTextEdit->setVisible(isVisible); +} + +void PasswordErrorTipsWidget::addErrorDetailMsg(const QString& msg) +{ + m_errorMsgNum ++; + m_detailTextEdit->append(QString("%1. ").arg(m_errorMsgNum) + msg); + m_showMore->setVisible(true); +} + +void PasswordErrorTipsWidget::setErrorTips(const QString &tips) +{ + m_tipLabel->setText(tips); +} + +void PasswordErrorTipsWidget::paintEvent(QPaintEvent *event) +{ + // 创建绘图对象 + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿 + + // 设置画笔和画刷 + painter.setPen(Qt::NoPen); + painter.setBrush(QColor(164, 166, 189, 255)); // 半透明灰色 + + // 绘制圆角矩形 + QRectF rect = QRectF(0, 0, width(), height()); + painter.drawRoundedRect(rect, 10, 8); + + QWidget::paintEvent(event); +} + +void PasswordErrorTipsWidget::reset() +{ + m_errorMsgNum = 0; + m_detailTextEdit->clear(); + m_detailTextEdit->hide(); + m_tipLabel->clear(); +} + +bool PasswordErrorTipsWidget::hasErrorTips() +{ + return !m_tipLabel->text().isEmpty(); +} diff --git a/src/widgets/passworderrortipswidget.h b/src/widgets/passworderrortipswidget.h new file mode 100644 index 00000000..55918df5 --- /dev/null +++ b/src/widgets/passworderrortipswidget.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PASSWORDTIPSWIDGET_H +#define PASSWORDTIPSWIDGET_H + +#include +#include +#include + +#include "QWidget" +#include "QLabel" +#include "QPushButton" +#include "QScrollArea" + +DWIDGET_USE_NAMESPACE + +class PasswordErrorTipsWidget : public QWidget +{ + Q_OBJECT +public: + explicit PasswordErrorTipsWidget(QWidget *parent = nullptr); + void initUi(); + + void reset(); + void setErrDetailVisible(bool isVisible); + void addErrorDetailMsg(const QString& msg); + void setErrorTips(const QString &tips); + bool hasErrorTips(); + +protected: + bool eventFilter(QObject *watch, QEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + DLabel* m_tipLabel; + DLabel* m_showMore; + DTextEdit* m_detailTextEdit; + QWidget* m_tipsWidget; + + int m_errorMsgNum; +}; + + +#endif //PASSWORDTIPSWIDGET_H diff --git a/src/widgets/popupwindow.cpp b/src/widgets/popupwindow.cpp new file mode 100644 index 00000000..8a5d2a07 --- /dev/null +++ b/src/widgets/popupwindow.cpp @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "popupwindow.h" + +#include +#include + +PopupWindow::PopupWindow(QWidget *parent) + : DArrowRectangle(ArrowBottom, FloatWidget, parent) +{ + setMargin(0); + + setBackgroundColor(QColor(235, 235, 235, 80)); + setBorderColor(QColor(235, 235, 235, 80)); + + setWindowFlags(Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); + setShadowBlurRadius(20); + setRadius(6); + setShadowYOffset(2); + setShadowXOffset(0); + setArrowWidth(18); + setArrowHeight(10); +} + +PopupWindow::~PopupWindow() +{ +} + +void PopupWindow::setContent(QWidget *content) +{ + QWidget *lastWidget = getContent(); + if (lastWidget) + lastWidget->removeEventFilter(this); + content->installEventFilter(this); + + QAccessibleEvent event(this, QAccessible::NameChanged); + QAccessible::updateAccessibility(&event); + + if (!content->objectName().trimmed().isEmpty()) + setAccessibleName(content->objectName() + "-popup"); + + DArrowRectangle::setContent(content); +} + +void PopupWindow::toggle(const QPoint &pos) +{ + isVisible() ? hide() : show(pos); +} + +void PopupWindow::show(const QPoint &pos) +{ + m_lastPoint = pos; + if (getContent()) + getContent()->setVisible(true); + DArrowRectangle::show(pos.x(), pos.y()); +} + +void PopupWindow::hide() +{ + if (getContent()) + getContent()->setVisible(false); + Q_EMIT visibleChanged(false); + DArrowRectangle::hide(); +} + +void PopupWindow::showEvent(QShowEvent *e) +{ + Q_EMIT visibleChanged(true); + DArrowRectangle::showEvent(e); + + QTimer::singleShot(0, this, &PopupWindow::ensureRaised); +} +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void PopupWindow::enterEvent(QEnterEvent *e) +#else +void PopupWindow::enterEvent(QEvent *e) +#endif +{ + DArrowRectangle::enterEvent(e); + + QTimer::singleShot(0, this, &PopupWindow::ensureRaised); +} + +bool PopupWindow::eventFilter(QObject *o, QEvent *e) +{ + if (o != getContent() || e->type() != QEvent::Resize) + return false; + + // FIXME: ensure position move after global mouse release event + // 目的是为了在content resize之后重新设置弹窗的位置和大小 + if (isVisible()) { + QTimer::singleShot(0, this, [this] { + // NOTE(sbw): double check is necessary, in this time, the popup maybe already hided. + if (isVisible()) + show(m_lastPoint); + }); + } + + return false; +} + +void PopupWindow::ensureRaised() +{ + if (isVisible()) { + QWidget *content = getContent(); + if (!content || !content->isVisible()) { + this->setVisible(false); + } else { + raise(); + } + } +} diff --git a/src/widgets/popupwindow.h b/src/widgets/popupwindow.h new file mode 100644 index 00000000..3a01c033 --- /dev/null +++ b/src/widgets/popupwindow.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef POPUPWINDOW_H +#define POPUPWINDOW_H + +#include + +class PopupWindow : public Dtk::Widget::DArrowRectangle +{ + Q_OBJECT + +public: + explicit PopupWindow(QWidget *parent = 0); + ~PopupWindow(); + + bool model() const; + + void setContent(QWidget *content); + + using Dtk::Widget::DArrowRectangle::show; + void show(const QPoint &pos); + void toggle(const QPoint &pos); + void hide(); + +protected: + void showEvent(QShowEvent *e) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *e) override; +#else + void enterEvent(QEvent *e) override; +#endif + bool eventFilter(QObject *o, QEvent *e) override; + +signals: + void visibleChanged(bool visible); + +private slots: + void ensureRaised(); + +private: + QPoint m_lastPoint; +}; + +#endif // POPUPWINDOW_H diff --git a/src/widgets/propertygroup.cpp b/src/widgets/propertygroup.cpp index 3849aa81..3683dd36 100644 --- a/src/widgets/propertygroup.cpp +++ b/src/widgets/propertygroup.cpp @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: zccrs - * - * Maintainer: zccrs - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "propertygroup.h" #include @@ -84,8 +68,13 @@ void PropertyGroup::addProperty(const QByteArray &propertyName) m_signalMapperMap[propertyName] = mapper; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + connect(mapper, static_cast(&QSignalMapper::mappedObject), + this, &PropertyGroup::onObjectPropertyChanged); +#else connect(mapper, static_cast(&QSignalMapper::mapped), this, &PropertyGroup::onObjectPropertyChanged); +#endif } void PropertyGroup::removeProperty(const QByteArray &propertyName) diff --git a/src/widgets/propertygroup.h b/src/widgets/propertygroup.h index fbff54d8..0528ea08 100644 --- a/src/widgets/propertygroup.h +++ b/src/widgets/propertygroup.h @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2017 ~ 2019 Deepin Technology Co., Ltd. - * - * Author: zccrs - * - * Maintainer: zccrs - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef PROPERTYGROUP_H #define PROPERTYGROUP_H diff --git a/src/widgets/rounditembutton.cpp b/src/widgets/rounditembutton.cpp index 14e56bc2..ad96bd89 100644 --- a/src/widgets/rounditembutton.cpp +++ b/src/widgets/rounditembutton.cpp @@ -1,37 +1,18 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include #include #include "rounditembutton.h" -#include "../global_util/gsettingwatcher.h" #include DWIDGET_USE_NAMESPACE +const int iconWidthHeight = 74; +const int iconTextGap = 11; + RoundItemButton::RoundItemButton(QWidget *parent) : RoundItemButton("", parent) { @@ -82,22 +63,20 @@ void RoundItemButton::initConnect() connect(this, &RoundItemButton::stateChanged, this, static_cast(&RoundItemButton::update)); connect(this, &RoundItemButton::iconChanged, this, &RoundItemButton::updateIcon); connect(this, &RoundItemButton::toggled, this, &RoundItemButton::setChecked); - // connect(signalManager, &SignalManager::setButtonHover, [this] (const QString &text) { - // if (m_itemText->text() != text && !isChecked() && !isDisabled()) { - // updateState(Normal); - // } - // }); } void RoundItemButton::initUI() { setFocusPolicy(Qt::NoFocus); - setFixedSize(144, 164); + setFixedSize(144, 230); setCheckable(true); - DFontSizeManager::instance()->bind(this, DFontSizeManager::T6); + DFontSizeManager::instance()->bind(this, DFontSizeManager::T5); } - +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void RoundItemButton::enterEvent(QEnterEvent* event) +#else void RoundItemButton::enterEvent(QEvent* event) +#endif { Q_UNUSED(event) @@ -155,7 +134,11 @@ void RoundItemButton::paintEvent(QPaintEvent* event) // 计算文本行数 QStringList textList; QString str = m_text; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + while (fontMetrics().horizontalAdvance(str) > width() - 20 && str.length() > 0) { +#else while (fontMetrics().width(str) > width() - 20 && str.length() > 0) { +#endif int lastSpacePos = str.lastIndexOf(" "); if (lastSpacePos == -1) { str = fontMetrics().elidedText(str, Qt::ElideRight, width() - 2 * padding); @@ -168,28 +151,34 @@ void RoundItemButton::paintEvent(QPaintEvent* event) if (str.length() != m_text.length() && m_text.contains(str)) { textList.append(fontMetrics().elidedText(m_text.mid(m_text.indexOf(str) + str.length()), Qt::ElideRight, width() - 20)); } + // 计算图标绘制的区域 + QRect iconRect; + iconRect.setX((width() - iconWidthHeight) / 2); + iconRect.setY((height() - 2 * lineHeight- iconWidthHeight) / 2); + iconRect.setWidth(iconWidthHeight); + iconRect.setHeight(iconWidthHeight); // 计算文本绘制的区域 int textWidth = 0; for (auto text : textList) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + textWidth = qMax(textWidth, fontMetrics().horizontalAdvance(text)); +#else textWidth = qMax(textWidth, fontMetrics().width(text)); +#endif } QRect textRect; textRect.setX((width() - qMin(width(), textWidth + 2 * padding)) / 2); - textRect.setY(rect().y() + height() - 2 * lineHeight); + textRect.setY(iconRect.bottom() + iconTextGap); textRect.setWidth(qMin(width(), textWidth + 2 * padding)); textRect.setHeight(textList.size() * lineHeight); - // 计算图标绘制的区域 - const int minSize = qMin(width(), height() - 2 * lineHeight - 2 * padding); - QRect iconRect; - iconRect.setX((width() - minSize) / 2); - iconRect.setY((height() - 2 * lineHeight- minSize) / 2); - iconRect.setWidth(minSize); - iconRect.setHeight(minSize); if (m_state == Checked) { - painter.setBrush(QColor(0, 15, 39, 178)); + QColor color(Qt::white); + color.setAlphaF(0.03); + painter.setPen(Qt::NoPen); + painter.setBrush(color); painter.setRenderHint(QPainter::Antialiasing, true); // 绘制图标背景 @@ -200,9 +189,10 @@ void RoundItemButton::paintEvent(QPaintEvent* event) painter.drawRoundedRect(itemTextRect, m_rectRadius, m_rectRadius); QPen pen; - QColor penColor(151, 151, 151, 127); + QColor penColor(Qt::white); + penColor.setAlphaF(0.5); pen.setColor(penColor); - pen.setWidth(m_penWidth * 2); + pen.setWidth(m_penWidth * 3); painter.setPen(pen); painter.setRenderHint(QPainter::Antialiasing, true); @@ -211,6 +201,8 @@ void RoundItemButton::paintEvent(QPaintEvent* event) painter.drawEllipse(iconBackgroundRect); // 绘制文本区域边框 + pen.setWidth(m_penWidth * 2); + painter.setPen(pen); QRect textBackgroundRect(textRect.marginsRemoved(QMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth))); painter.drawRoundedRect(textBackgroundRect, m_rectRadius, m_rectRadius); } else if (m_state == Hover) { @@ -224,7 +216,9 @@ void RoundItemButton::paintEvent(QPaintEvent* event) } else if (m_state == Normal) { // 绘制鼠标选中的白色背景 painter.setPen(Qt::NoPen); - painter.setBrush(QColor(255, 255, 255, int(0.1 * 255))); + QColor color(Qt::white); + color.setAlphaF(0.15); + painter.setBrush(color); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawEllipse(iconRect); } @@ -257,6 +251,17 @@ void RoundItemButton::paintEvent(QPaintEvent* event) painter.drawText(lineRect, Qt::AlignCenter, textList.at(i)); } + + // 绘制文字旁的小红点 + if (m_redPointVisible) { + QRect textRt(textRect.x(), textRect.y(), textRect.width(), textList.size() * lineHeight); + const int spaceToText = 4; //文字和红点的距离 + const int radius = 3; //红点的半径 + QPoint centerOfCircle=textRt.topRight() + QPoint(spaceToText, textRt.height() / 2); + painter.setBrush(QBrush(Qt::red)); + painter.setPen(Qt::red); + painter.drawEllipse(centerOfCircle, radius, radius); + } } void RoundItemButton::updateIcon() @@ -305,3 +310,10 @@ void RoundItemButton::setPressPic(const QString &path) updateIcon(); } + +void RoundItemButton::setRedPointVisible(bool visible) +{ + m_redPointVisible = visible; + + update(); +} diff --git a/src/widgets/rounditembutton.h b/src/widgets/rounditembutton.h index 128a4e51..b1731f6f 100644 --- a/src/widgets/rounditembutton.h +++ b/src/widgets/rounditembutton.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef ROUNDITEMBUTTON #define ROUNDITEMBUTTON @@ -66,6 +45,7 @@ class RoundItemButton: public QAbstractButton void setNormalPic(const QString &path); void setHoverPic(const QString &path); void setPressPic(const QString &path); + void setRedPointVisible(bool visible); signals: void stateChanged(const State state); @@ -78,7 +58,11 @@ private slots: protected: void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE; - void enterEvent(QEvent* event) Q_DECL_OVERRIDE; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *e) override; +#else + void enterEvent(QEvent *e) override; +#endif void leaveEvent(QEvent* event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent* e) Q_DECL_OVERRIDE; @@ -97,5 +81,6 @@ private slots: QString m_hoverIcon; QString m_pressedIcon; QString m_currentIcon; + bool m_redPointVisible = false; }; #endif // ROUNDITEMBUTTON diff --git a/src/widgets/shutdown_black_widget.cpp b/src/widgets/shutdown_black_widget.cpp new file mode 100644 index 00000000..b2d08d77 --- /dev/null +++ b/src/widgets/shutdown_black_widget.cpp @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "shutdown_black_widget.h" +#include + +#include +#include +#include +#include +#include +#include + +bool onPreparingForShutdown() { + QDBusInterface iface( + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + QDBusConnection::systemBus() + ); + QVariant preparingForShutdown = iface.property("PreparingForShutdown"); + + if (preparingForShutdown.isValid()) { + bool isPreparing = preparingForShutdown.toBool(); + qDebug() << "Preparing for shutdown property value:" << isPreparing; + return isPreparing; + } else { + qWarning() << "Failed to retrieve preparing for shutdown property, the property is invalid"; + } + return false; +} + +void handleSIGTERM(int signal) { + qInfo() << "handleSIGTERM: " << signal; + + bool bShutdown = onPreparingForShutdown(); + qInfo() << "Whether preparing for shutdown: " << bShutdown; + if (bShutdown) { + QTimer::singleShot(2500, qApp, SLOT(quit())); + } else { + QTimer time; + time.start(1000); + QObject::connect(&time, &QTimer::timeout, [&] { + bool bShutdown = onPreparingForShutdown(); + qInfo() << "Whether preparing for shutdown: " << bShutdown; + if (bShutdown) { + time.stop(); + QTimer::singleShot(2000, qApp, SLOT(quit())); + return; + } else { + qInfo() << " Get org.freedesktop.login1.Manager PreparingForShutdown again."; + } + }); + } +} + +ShutdownBlackWidget::ShutdownBlackWidget(QWidget *parent) + : QWidget(parent) + , m_cursor(cursor()) +{ + signal(SIGTERM, handleSIGTERM); + setObjectName(QStringLiteral("ShutdownBlackWidget")); + setAccessibleName(QStringLiteral("ShutdownBlackWidget")); + setVisible(false); + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + + QCursor cursor(Qt::BlankCursor); + this->setCursor(cursor); + + installEventFilter(this); +} + +void ShutdownBlackWidget::setBlackMode(const bool isBlackMode) +{ + qInfo() << "ShutdownBlackWidget setBlackMode : " << isBlackMode; + setVisible(isBlackMode); + if (isBlackMode) { + show(); + } +#ifndef QT_DEBUG + setCursor(isBlackMode ? Qt::BlankCursor : m_cursor); +#endif +} + +void ShutdownBlackWidget::setShutdownMode(const bool isBlackMode) +{ + setVisible(isBlackMode); +} + +void ShutdownBlackWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + QRect rect(QPoint(0, 0), QSize(size() * devicePixelRatioF())); + painter.fillRect(rect, Qt::black); + + QWidget::paintEvent(event); +} + +void ShutdownBlackWidget::showEvent(QShowEvent *event) +{ + raise(); + grabMouse(); + grabKeyboard(); + QWidget::showEvent(event); +} + +bool ShutdownBlackWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseButtonRelease || + event->type() == QEvent::MouseButtonDblClick || + event->type() == QEvent::MouseMove || + event->type() == QEvent::KeyPress || + event->type() == QEvent::KeyRelease) { + qDebug() << "### All Mouse and Keyboard Event blocked!"; + + // 返回 true 表示事件已被处理,不再继续传递 + return true; + } + + return QWidget::eventFilter(watched, event); +} diff --git a/src/widgets/shutdown_black_widget.h b/src/widgets/shutdown_black_widget.h new file mode 100644 index 00000000..a200f386 --- /dev/null +++ b/src/widgets/shutdown_black_widget.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +class ShutdownBlackWidget : public QWidget +{ + Q_OBJECT +public: + explicit ShutdownBlackWidget(QWidget *parent = nullptr); + + void setBlackMode(const bool isBlackMode); + +public Q_SLOTS: + void setShutdownMode(const bool isBlackMode = false); + +protected: + void paintEvent(QPaintEvent *event) override; + void showEvent(QShowEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QCursor m_cursor; +}; + +// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/widgets/shutdownwidget.cpp b/src/widgets/shutdownwidget.cpp index 33cec5a6..873a3afe 100644 --- a/src/widgets/shutdownwidget.cpp +++ b/src/widgets/shutdownwidget.cpp @@ -1,34 +1,14 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "shutdownwidget.h" -#include "multiuserswarningview.h" #include "../global_util/gsettingwatcher.h" -#include "../global_util/public_func.h" +#include "dconfig_helper.h" -#include +#ifdef ENABLE_DSS_SNIPE +#include "dconfigwatcher.h" +#endif #if 0 // storage i10n QT_TRANSLATE_NOOP("ShutdownWidget", "Shut down"), @@ -37,92 +17,135 @@ QT_TRANSLATE_NOOP("ShutdownWidget", "Suspend"), QT_TRANSLATE_NOOP("ShutdownWidget", "Hibernate") #endif +#ifdef ENABLE_DSS_SNIPE +const QString LASTORE_DCONFIG_NAME = "org.deepin.dde.lastore"; +#else +const QString LASTORE_DCONFIG_NAME = "org.deepin.lastore"; +#endif + +const QString LASTORE_DAEMON_STATUS = "lastore-daemon-status"; +const int IS_UPDATE_READY = 1 << 0; +const int IS_UPDATE_DISABLED = 1 << 1; +const int IS_UPDATE_FORCE = 1 << 2; + DCORE_USE_NAMESPACE ShutdownWidget::ShutdownWidget(QWidget *parent) : QFrame(parent) , m_index(-1) , m_model(nullptr) + , m_shutdownFrame(nullptr) , m_systemMonitor(nullptr) + , m_actionFrame(nullptr) + , m_mainLayout(nullptr) + , m_shutdownLayout(nullptr) + , m_actionLayout(nullptr) + , m_currentSelectedBtn(nullptr) + , m_requireShutdownButton(nullptr) + , m_requireRestartButton(nullptr) + , m_requireSuspendButton(nullptr) + , m_requireHibernateButton(nullptr) + , m_requireLockButton(nullptr) + , m_requireLogoutButton(nullptr) + , m_requireSwitchUserBtn(nullptr) + , m_requireSwitchSystemBtn(nullptr) + , m_updateAndShutdownButton(nullptr) + , m_updateAndRebootButton(nullptr) , m_switchosInterface(new HuaWeiSwitchOSInterface("com.huawei", "/com/huawei/switchos", QDBusConnection::sessionBus(), this)) - , m_dconfig(DConfig::create(getDefaultConfigFileName(), getDefaultConfigFileName(), QString(), this)) + , m_modeStatus(SessionBaseModel::ModeStatus::NoStatus) { - m_frameDataBind = FrameDataBind::Instance(); - initUI(); initConnect(); +#ifndef ENABLE_DSS_SNIPE onEnable("systemShutdown", enableState(GSettingWatcher::instance()->getStatus("systemShutdown"))); onEnable("systemSuspend", enableState(GSettingWatcher::instance()->getStatus("systemSuspend"))); onEnable("systemHibernate", enableState(GSettingWatcher::instance()->getStatus("systemHibernate"))); onEnable("systemLock", enableState(GSettingWatcher::instance()->getStatus("systemLock"))); + onEnable("systemReboot", enableState(GSettingWatcher::instance()->getStatus("systemReboot"))); +#else + onEnable("systemShutdown", enableState(DConfigWatcher::instance()->getStatus("systemShutdown"))); + onEnable("systemSuspend", enableState(DConfigWatcher::instance()->getStatus("systemSuspend"))); + onEnable("systemHibernate", enableState(DConfigWatcher::instance()->getStatus("systemHibernate"))); + onEnable("systemLock", enableState(DConfigWatcher::instance()->getStatus("systemLock"))); + onEnable("systemReboot", enableState(DConfigWatcher::instance()->getStatus("systemReboot"))); +#endif - std::function function = std::bind(&ShutdownWidget::onOtherPageChanged, this, std::placeholders::_1); - int index = m_frameDataBind->registerFunction("ShutdownWidget", function); - - connect(this, &ShutdownWidget::destroyed, this, [this, index] { - m_frameDataBind->unRegisterFunction("ShutdownWidget", index); - }); installEventFilter(this); } ShutdownWidget::~ShutdownWidget() { +#ifndef ENABLE_DSS_SNIPE GSettingWatcher::instance()->erase("systemSuspend"); GSettingWatcher::instance()->erase("systemHibernate"); GSettingWatcher::instance()->erase("systemShutdown"); + GSettingWatcher::instance()->erase("systemLock"); + GSettingWatcher::instance()->erase("systemReboot"); +#else + DConfigWatcher::instance()->erase("systemSuspend"); + DConfigWatcher::instance()->erase("systemHibernate"); + DConfigWatcher::instance()->erase("systemShutdown"); + DConfigWatcher::instance()->erase("systemLock"); + DConfigWatcher::instance()->erase("systemReboot"); +#endif } void ShutdownWidget::initConnect() { - connect(m_requireRestartButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireRestartButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireRestartButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireRestart, false); }); - connect(m_requireShutdownButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireShutdownButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireShutdownButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireShutdown, false); }); - connect(m_requireSuspendButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireSuspendButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireSuspendButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireSuspend, false); }); - connect(m_requireHibernateButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireHibernateButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireHibernateButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireHibernate, false); }); - connect(m_requireLockButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireLockButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireLockButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireLock, false); }); - connect(m_requireSwitchUserBtn, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireSwitchUserBtn, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireSwitchUserBtn; onRequirePowerAction(SessionBaseModel::PowerAction::RequireSwitchUser, false); }); if (m_requireSwitchSystemBtn) { - connect(m_requireSwitchSystemBtn, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireSwitchSystemBtn, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireSwitchSystemBtn; onRequirePowerAction(SessionBaseModel::PowerAction::RequireSwitchSystem, false); }); } - connect(m_requireLogoutButton, &RoundItemButton::clicked, this, [ = ] { + connect(m_requireLogoutButton, &RoundItemButton::clicked, this, [this] { m_currentSelectedBtn = m_requireLogoutButton; onRequirePowerAction(SessionBaseModel::PowerAction::RequireLogout, false); }); - + connect(m_updateAndRebootButton, &RoundItemButton::clicked, this, [this] { + m_currentSelectedBtn = m_updateAndRebootButton; + onRequirePowerAction(SessionBaseModel::PowerAction::RequireUpdateRestart, false); + }); + connect(m_updateAndShutdownButton, &RoundItemButton::clicked, this, [this] { + m_currentSelectedBtn = m_updateAndShutdownButton; + onRequirePowerAction(SessionBaseModel::PowerAction::RequireUpdateShutdown, false); + }); +#ifndef ENABLE_DSS_SNIPE connect(GSettingWatcher::instance(), &GSettingWatcher::enableChanged, this, &ShutdownWidget::onEnable); +#else + connect(DConfigWatcher::instance(), &DConfigWatcher::enableChanged, this, &ShutdownWidget::onEnable); +#endif if (m_systemMonitor) { - connect(m_systemMonitor, &SystemMonitor::requestShowSystemMonitor, this, &ShutdownWidget::runSystemMonitor); + connect(m_systemMonitor, &SystemMonitor::requestAction, this, &ShutdownWidget::runSystemMonitor); } - connect(m_dconfig, &DConfig::valueChanged, this, [this] (const QString &key) { - if (key == "hideLogoutButton") { - if (m_requireLogoutButton && m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { - m_requireLogoutButton->setVisible(!m_dconfig->value("hideLogoutButton", false).toBool()); - } - } - }); + DConfigHelper::instance()->bind(this, "hideLogoutButton", &ShutdownWidget::onDConfigPropertyChanged); } void ShutdownWidget::updateTr(RoundItemButton *widget, const QString &tr) @@ -130,6 +153,7 @@ void ShutdownWidget::updateTr(RoundItemButton *widget, const QString &tr) m_trList << std::pair, QString>(std::bind(&RoundItemButton::setText, widget, std::placeholders::_1), tr); } +#ifndef ENABLE_DSS_SNIPE bool ShutdownWidget::enableState(const QString &gsettingsValue) { if ("Disabled" == gsettingsValue) @@ -137,41 +161,30 @@ bool ShutdownWidget::enableState(const QString &gsettingsValue) else return true; } +#else +bool ShutdownWidget::enableState(int settingsValue) +{ + if (Status_Disabled == settingsValue) + return false; + + return true; +} +#endif -void ShutdownWidget::onEnable(const QString &gsettingsName, bool enable) +void ShutdownWidget::onEnable(const QString &key, bool enable) { - if ("systemShutdown" == gsettingsName) { + if ("systemShutdown" == key) { m_requireShutdownButton->setDisabled(!enable); - } else if ("systemSuspend" == gsettingsName) { + } else if ("systemSuspend" == key) { m_requireSuspendButton->setDisabled(!enable); m_requireSuspendButton->setCheckable(enable); - } else if ("systemHibernate" == gsettingsName) { + } else if ("systemHibernate" == key) { m_requireHibernateButton->setDisabled(!enable); m_requireHibernateButton->setCheckable(enable); - } else if ("systemLock" == gsettingsName) { + } else if ("systemLock" == key) { m_requireLockButton->setDisabled(!enable); - } -} - -void ShutdownWidget::onOtherPageChanged(const QVariant &value) -{ - m_index = value.toInt(); - - for (auto it = m_btnList.constBegin(); it != m_btnList.constEnd(); ++it) { - (*it)->updateState(RoundItemButton::Normal); - } - - m_currentSelectedBtn = m_btnList.at(m_index); - m_currentSelectedBtn->updateState(RoundItemButton::Checked); -} - -void ShutdownWidget::hideToplevelWindow() -{ - QWidgetList widgets = qApp->topLevelWidgets(); - for (QWidget *widget : widgets) { - if (widget->isVisible()) { - widget->hide(); - } + } else if ("systemReboot" == key) { + m_requireRestartButton->setDisabled(!enable); } } @@ -182,7 +195,8 @@ void ShutdownWidget::enterKeyPushed() return; } - if (!m_currentSelectedBtn->isEnabled()) + // 在按回车键时,若m_currentSelectedBtn不存在,则退出 + if (!m_currentSelectedBtn || !m_currentSelectedBtn->isEnabled() || !m_currentSelectedBtn->isVisible()) return; if (m_currentSelectedBtn == m_requireShutdownButton) @@ -201,69 +215,116 @@ void ShutdownWidget::enterKeyPushed() onRequirePowerAction(SessionBaseModel::PowerAction::RequireSwitchSystem, false); else if (m_currentSelectedBtn == m_requireLogoutButton) onRequirePowerAction(SessionBaseModel::PowerAction::RequireLogout, false); + else if (m_currentSelectedBtn == m_updateAndShutdownButton) + onRequirePowerAction(SessionBaseModel::PowerAction::RequireUpdateShutdown, false); + else if (m_currentSelectedBtn == m_updateAndRebootButton) + onRequirePowerAction(SessionBaseModel::PowerAction::RequireUpdateRestart, false); } void ShutdownWidget::enableHibernateBtn(bool enable) { +#ifndef ENABLE_DSS_SNIPE m_requireHibernateButton->setVisible(enable && (GSettingWatcher::instance()->getStatus("systemHibernate") != "Hiden")); +#else + m_requireHibernateButton->setVisible(enable && (DConfigWatcher::instance()->getStatus("systemHibernate") != Status_Hidden)); +#endif } void ShutdownWidget::enableSleepBtn(bool enable) { +#ifndef ENABLE_DSS_SNIPE m_requireSuspendButton->setVisible(enable && (GSettingWatcher::instance()->getStatus("systemSuspend") != "Hiden")); +#else + m_requireSuspendButton->setVisible(enable && (DConfigWatcher::instance()->getStatus("systemSuspend") != Status_Hidden)); +#endif } void ShutdownWidget::initUI() { setFocusPolicy(Qt::StrongFocus); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + auto setPic = [](RoundItemButton* button, const QString &pic) { + button->setNormalPic(":/img/list_actions/" + pic + "_normal.svg"); + button->setHoverPic(":/img/list_actions/" + pic + "_hover.svg"); + button->setPressPic(":/img/list_actions/" + pic + "_press.svg"); + }; + m_requireShutdownButton = new RoundItemButton(this); + setPic(m_requireShutdownButton, "poweroff"); m_requireShutdownButton->setFocusPolicy(Qt::NoFocus); m_requireShutdownButton->setObjectName("RequireShutDownButton"); m_requireShutdownButton->setAccessibleName("RequireShutDownButton"); m_requireShutdownButton->setAutoExclusive(true); updateTr(m_requireShutdownButton, "Shut down"); +#ifndef ENABLE_DSS_SNIPE GSettingWatcher::instance()->bind("systemShutdown", m_requireShutdownButton); // GSettings配置项 +#else + DConfigWatcher::instance()->bind("systemShutdown", m_requireShutdownButton); +#endif m_requireRestartButton = new RoundItemButton(tr("Reboot"), this); + setPic(m_requireRestartButton, "reboot"); m_requireRestartButton->setFocusPolicy(Qt::NoFocus); m_requireRestartButton->setObjectName("RequireRestartButton"); m_requireRestartButton->setAccessibleName("RequireRestartButton"); m_requireRestartButton->setAutoExclusive(true); updateTr(m_requireRestartButton, "Reboot"); +#ifndef ENABLE_DSS_SNIPE + GSettingWatcher::instance()->bind("systemReboot", m_requireRestartButton); // GSettings配置项 +#else + DConfigWatcher::instance()->bind("systemReboot", m_requireRestartButton); +#endif m_requireSuspendButton = new RoundItemButton(tr("Suspend"), this); + setPic(m_requireSuspendButton, "suspend"); m_requireSuspendButton->setFocusPolicy(Qt::NoFocus); m_requireSuspendButton->setObjectName("RequireSuspendButton"); m_requireSuspendButton->setAccessibleName("RequireSuspendButton"); m_requireSuspendButton->setAutoExclusive(true); updateTr(m_requireSuspendButton, "Suspend"); +#ifndef ENABLE_DSS_SNIPE GSettingWatcher::instance()->bind("systemSuspend", m_requireSuspendButton); // GSettings配置项 +#else + DConfigWatcher::instance()->bind("systemSuspend", m_requireSuspendButton); +#endif m_requireHibernateButton = new RoundItemButton(tr("Hibernate"), this); + setPic(m_requireHibernateButton, "sleep"); m_requireHibernateButton->setFocusPolicy(Qt::NoFocus); m_requireHibernateButton->setAccessibleName("RequireHibernateButton"); m_requireHibernateButton->setObjectName("RequireHibernateButton"); m_requireHibernateButton->setAutoExclusive(true); updateTr(m_requireHibernateButton, "Hibernate"); +#ifndef ENABLE_DSS_SNIPE GSettingWatcher::instance()->bind("systemHibernate", m_requireHibernateButton); // GSettings配置项 +#else + DConfigWatcher::instance()->bind("systemHibernate", m_requireHibernateButton); +#endif m_requireLockButton = new RoundItemButton(tr("Lock")); + setPic(m_requireLockButton, "lock"); m_requireLockButton->setFocusPolicy(Qt::NoFocus); m_requireLockButton->setAccessibleName("RequireLockButton"); m_requireLockButton->setObjectName("RequireLockButton"); m_requireLockButton->setAutoExclusive(true); updateTr(m_requireLockButton, "Lock"); +#ifndef ENABLE_DSS_SNIPE GSettingWatcher::instance()->bind("systemLock", m_requireLockButton); // GSettings配置项 +#else + DConfigWatcher::instance()->bind("systemLock", m_requireLockButton); +#endif m_requireLogoutButton = new RoundItemButton(tr("Log out")); + setPic(m_requireLogoutButton, "logout"); m_requireLogoutButton->setFocusPolicy(Qt::NoFocus); m_requireLogoutButton->setAccessibleName("RequireLogoutButton"); m_requireLogoutButton->setObjectName("RequireLogoutButton"); m_requireLogoutButton->setAutoExclusive(true); - m_requireLogoutButton->setVisible(!m_dconfig->value("hideLogoutButton", false).toBool()); updateTr(m_requireLogoutButton, "Log out"); m_requireSwitchUserBtn = new RoundItemButton(tr("Switch user")); + setPic(m_requireSwitchUserBtn, "userswitch"); m_requireSwitchUserBtn->setFocusPolicy(Qt::NoFocus); m_requireSwitchUserBtn->setAccessibleName("RequireSwitchUserButton"); m_requireSwitchUserBtn->setObjectName("RequireSwitchUserButton"); @@ -273,6 +334,7 @@ void ShutdownWidget::initUI() if (m_switchosInterface->isDualOsSwitchAvail()) { m_requireSwitchSystemBtn = new RoundItemButton(tr("Switch system")); + setPic(m_requireSwitchSystemBtn, "osswitch"); m_requireSwitchSystemBtn->setAccessibleName("SwitchSystemButton"); m_requireSwitchSystemBtn->setFocusPolicy(Qt::NoFocus); m_requireSwitchSystemBtn->setObjectName("RequireSwitchSystemButton"); @@ -280,8 +342,26 @@ void ShutdownWidget::initUI() updateTr(m_requireSwitchSystemBtn, "Switch system"); } + m_updateAndShutdownButton = new RoundItemButton(tr("Update and Shut Down")); + setPic(m_updateAndShutdownButton, "poweroff"); + m_updateAndShutdownButton->setFocusPolicy(Qt::NoFocus); + m_updateAndShutdownButton->setAccessibleName("UpdateAndShutdownButton"); + m_updateAndShutdownButton->setObjectName("UpdateAndShutdownButton"); + m_updateAndShutdownButton->setAutoExclusive(true); + m_updateAndShutdownButton->setVisible(false); + + m_updateAndRebootButton = new RoundItemButton(tr("Update and Reboot")); + setPic(m_updateAndRebootButton, "reboot"); + m_updateAndRebootButton->setFocusPolicy(Qt::NoFocus); + m_updateAndRebootButton->setAccessibleName("UpdateAndRebootButton"); + m_updateAndRebootButton->setObjectName("UpdateAndRebootButton"); + m_updateAndRebootButton->setAutoExclusive(true); + m_updateAndRebootButton->setVisible(false); + m_btnList.append(m_requireShutdownButton); + m_btnList.append(m_updateAndShutdownButton); m_btnList.append(m_requireRestartButton); + m_btnList.append(m_updateAndRebootButton); m_btnList.append(m_requireSuspendButton); m_btnList.append(m_requireHibernateButton); m_btnList.append(m_requireLockButton); @@ -292,11 +372,17 @@ void ShutdownWidget::initUI() m_btnList.append(m_requireLogoutButton); m_shutdownLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_shutdownLayout->setContentsMargins(0, 0, 0, 0); +#else m_shutdownLayout->setMargin(0); +#endif m_shutdownLayout->setSpacing(10); m_shutdownLayout->addStretch(); m_shutdownLayout->addWidget(m_requireShutdownButton); + m_shutdownLayout->addWidget(m_updateAndShutdownButton); m_shutdownLayout->addWidget(m_requireRestartButton); + m_shutdownLayout->addWidget(m_updateAndRebootButton); m_shutdownLayout->addWidget(m_requireSuspendButton); m_shutdownLayout->addWidget(m_requireHibernateButton); m_shutdownLayout->addWidget(m_requireLockButton); @@ -310,18 +396,21 @@ void ShutdownWidget::initUI() m_shutdownFrame = new QFrame; m_shutdownFrame->setAccessibleName("ShutdownFrame"); m_shutdownFrame->setLayout(m_shutdownLayout); + m_shutdownFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_actionLayout = new QVBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_actionLayout->setContentsMargins(0, 0, 0, 0); +#else m_actionLayout->setMargin(0); +#endif m_actionLayout->setSpacing(10); m_actionLayout->addStretch(); m_actionLayout->addWidget(m_shutdownFrame); - m_actionLayout->setAlignment(m_shutdownFrame, Qt::AlignCenter); m_actionLayout->addStretch(); if (findValueByQSettings(DDESESSIONCC::session_ui_configs, "Shutdown", "enableSystemMonitor", true)) { - QFile file("/usr/bin/deepin-system-monitor"); - if (file.exists()) { + if (!QStandardPaths::findExecutable("deepin-system-monitor").isEmpty()) { m_systemMonitor = new SystemMonitor; m_systemMonitor->setAccessibleName("SystemMonitor"); m_systemMonitor->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); @@ -332,20 +421,23 @@ void ShutdownWidget::initUI() } } - m_actionFrame = new QFrame; + m_actionFrame = new QFrame(this); m_actionFrame->setAccessibleName("ActionFrame"); - m_actionFrame->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + m_actionFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_actionFrame->setFocusPolicy(Qt::NoFocus); m_actionFrame->setLayout(m_actionLayout); m_mainLayout = new QStackedLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_mainLayout->setContentsMargins(0, 0, 0, 0); +#else m_mainLayout->setMargin(0); +#endif m_mainLayout->setSpacing(0); m_mainLayout->addWidget(m_actionFrame); - m_mainLayout->setAlignment(m_actionFrame, Qt::AlignCenter); setLayout(m_mainLayout); - updateStyle(":/skin/requireshutdown.qss", this); + // updateStyle(":/skin/requireshutdown.qss", this); // refresh language for (auto it = m_trList.constBegin(); it != m_trList.constEnd(); ++it) { @@ -372,9 +464,8 @@ void ShutdownWidget::leftKeySwitch() } m_currentSelectedBtn = m_btnList.at(m_index); - m_currentSelectedBtn->updateState(RoundItemButton::Checked); - - m_frameDataBind->updateValue("ShutdownWidget", m_index); + if (m_currentSelectedBtn) + m_currentSelectedBtn->updateState(RoundItemButton::Checked); if (m_systemMonitor && m_systemMonitor->isVisible()) { m_systemMonitor->setState(SystemMonitor::Leave); @@ -403,8 +494,6 @@ void ShutdownWidget::rightKeySwitch() m_currentSelectedBtn = m_btnList.at(m_index); m_currentSelectedBtn->updateState(RoundItemButton::Checked); - m_frameDataBind->updateValue("ShutdownWidget", m_index); - if (m_systemMonitor && m_systemMonitor->isVisible()) { m_systemMonitor->setState(SystemMonitor::Leave); } @@ -413,14 +502,66 @@ void ShutdownWidget::rightKeySwitch() void ShutdownWidget::onStatusChanged(SessionBaseModel::ModeStatus status) { RoundItemButton *roundItemButton; + if (m_modeStatus == status) { + qCInfo(DDE_SHELL) << "Shutdown widget status not being changed"; + return; + } + m_modeStatus = status; + setButtonsVisible(); + + if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { + // 如果用户点击了更新选项,那么直接开始进入更新 + if (m_model->updatePowerMode() != SessionBaseModel::UPM_None) { + roundItemButton = m_model->updatePowerMode() == SessionBaseModel::UPM_UpdateAndShutdown ? + m_updateAndShutdownButton : m_updateAndRebootButton; + // 当前流程执行完毕后模拟点击按钮 + QTimer::singleShot(0, this, [roundItemButton] { + Q_EMIT roundItemButton->clicked(); + }); + } else { + roundItemButton = m_requireLockButton; + } + } else { + roundItemButton = m_requireShutdownButton; + } + + m_index = m_btnList.indexOf(roundItemButton); + m_currentSelectedBtn = m_btnList.at(m_index); + m_currentSelectedBtn->updateState(RoundItemButton::Checked); + + if (m_systemMonitor) { + m_systemMonitor->setVisible(status == SessionBaseModel::ModeStatus::ShutDownMode); + } +} + +void ShutdownWidget::setButtonsVisible() +{ + // 根据lastore的lastore-daemon-status配置决定是否显示更新按钮 + const int lastoreDaemonStatus = DConfigHelper::instance()->getConfig(LASTORE_DCONFIG_NAME, LASTORE_DCONFIG_NAME, "", LASTORE_DAEMON_STATUS, 0).toInt(); + qCInfo(DDE_SHELL) << "Lastore daemon status: " << lastoreDaemonStatus; + const bool isUpdateReady = lastoreDaemonStatus & IS_UPDATE_READY; + const bool isUpdateDisabled = lastoreDaemonStatus & IS_UPDATE_DISABLED; + const bool isUpdateForce = lastoreDaemonStatus & IS_UPDATE_FORCE; + const bool isUpdateVisible = isUpdateReady && !isUpdateDisabled; + if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { +#ifndef ENABLE_DSS_SNIPE m_requireLockButton->setVisible(GSettingWatcher::instance()->getStatus("systemLock") != "Hiden"); +#else + m_requireLockButton->setVisible(DConfigWatcher::instance()->getStatus("systemLock") != Status_Hidden); +#endif m_requireSwitchUserBtn->setVisible(m_switchUserEnable); if (m_requireSwitchSystemBtn) { m_requireSwitchSystemBtn->setVisible(true); } - m_requireLogoutButton->setVisible(!m_dconfig->value("hideLogoutButton", false).toBool()); - roundItemButton = m_requireLockButton; + if (m_model->appType() == AppType::Lock) { + const bool hideLogoutButton = DConfigHelper::instance()->getConfig("hideLogoutButton", false).toBool(); + m_requireLogoutButton->setVisible(!hideLogoutButton); + } + m_updateAndRebootButton->setVisible(isUpdateVisible); + m_updateAndRebootButton->setRedPointVisible(isUpdateVisible); + m_updateAndShutdownButton->setVisible(isUpdateVisible); + m_updateAndShutdownButton->setRedPointVisible(isUpdateVisible); } else { m_requireLockButton->setVisible(false); m_requireSwitchUserBtn->setVisible(false); @@ -428,61 +569,66 @@ void ShutdownWidget::onStatusChanged(SessionBaseModel::ModeStatus status) m_requireSwitchSystemBtn->setVisible(false); } m_requireLogoutButton->setVisible(false); - roundItemButton = m_requireShutdownButton; + m_updateAndShutdownButton->setVisible(false); + m_updateAndRebootButton->setVisible(false); } - int index = m_btnList.indexOf(roundItemButton); - roundItemButton->updateState(RoundItemButton::Checked); - m_frameDataBind->updateValue("ShutdownWidget", index); - - if (m_systemMonitor) { - m_systemMonitor->setVisible(status == SessionBaseModel::ModeStatus::ShutDownMode); + if (isUpdateForce && isUpdateVisible) { + qCInfo(DDE_SHELL) << "Force update is enabled, hide shutdown button and reboot button"; + m_requireShutdownButton->setVisible(false); + m_requireRestartButton->setVisible(false); } } void ShutdownWidget::runSystemMonitor() { - QProcess::startDetached("/usr/bin/deepin-system-monitor"); + QProcess::startDetached("deepin-system-monitor", {}); if (m_systemMonitor) { m_systemMonitor->clearFocus(); m_systemMonitor->setState(SystemMonitor::Leave); } - hideToplevelWindow(); + m_model->setVisible(false); } void ShutdownWidget::recoveryLayout() { - //关机或重启确认前会隐藏所有按钮,取消重启或关机后隐藏界面时重置按钮可见状态 - //同时需要判断切换用户按钮是否允许可见 + // 关机或重启确认前会隐藏所有按钮,取消重启或关机后隐藏界面时重置按钮可见状态 + // 同时需要判断切换用户按钮是否允许可见 +#ifndef ENABLE_DSS_SNIPE m_requireShutdownButton->setVisible(true && (GSettingWatcher::instance()->getStatus("systemShutdown") != "Hiden")); - m_requireRestartButton->setVisible(true); + m_requireRestartButton->setVisible(GSettingWatcher::instance()->getStatus("systemReboot") != "Hiden"); +#else + m_requireShutdownButton->setVisible(true && (DConfigWatcher::instance()->getStatus("systemShutdown") != Status_Hidden)); + m_requireRestartButton->setVisible(DConfigWatcher::instance()->getStatus("systemReboot") != Status_Hidden); +#endif enableHibernateBtn(m_model->hasSwap()); enableSleepBtn(m_model->canSleep()); - m_requireLockButton->setVisible(true && (GSettingWatcher::instance()->getStatus("systemLock") != "Hiden")); - m_requireSwitchUserBtn->setVisible(m_switchUserEnable); - - if (m_systemMonitor) { - m_systemMonitor->setVisible(false); - } + if (m_modeStatus == SessionBaseModel::ModeStatus::PowerMode) + return; + m_requireSwitchUserBtn->setVisible(m_switchUserEnable); m_mainLayout->setCurrentWidget(m_actionFrame); setFocusPolicy(Qt::StrongFocus); } void ShutdownWidget::onRequirePowerAction(SessionBaseModel::PowerAction powerAction, bool needConfirm) { + qInfo() << "Require power action: " << powerAction << ", need confirm: " << needConfirm << ", m_model->appType(): " << m_model->appType(); + //锁屏或关机模式时,需要确认是否关机或检查是否有阻止关机 if (m_model->appType() == Lock) { switch (powerAction) { + //更新前检查是否允许关机 + case SessionBaseModel::PowerAction::RequireUpdateShutdown: + case SessionBaseModel::PowerAction::RequireUpdateRestart: case SessionBaseModel::PowerAction::RequireShutdown: case SessionBaseModel::PowerAction::RequireRestart: case SessionBaseModel::PowerAction::RequireSwitchSystem: case SessionBaseModel::PowerAction::RequireLogout: case SessionBaseModel::PowerAction::RequireSuspend: case SessionBaseModel::PowerAction::RequireHibernate: - m_model->setIsCheckedInhibit(false); emit m_model->shutdownInhibit(powerAction, needConfirm); break; default: @@ -497,7 +643,7 @@ void ShutdownWidget::onRequirePowerAction(SessionBaseModel::PowerAction powerAct void ShutdownWidget::setUserSwitchEnable(bool enable) { - //接收到用户列表变更信号号,记录切换用户是否允许可见,再根据当前是锁屏还是关机设置切换按钮可见状态 + // 接收到用户列表变更信号号,记录切换用户是否允许可见,再根据当前是锁屏还是关机设置切换按钮可见状态 if (m_switchUserEnable == enable) { return; } @@ -511,7 +657,7 @@ bool ShutdownWidget::eventFilter(QObject *watched, QEvent *event) Q_UNUSED(watched) if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Tab) { + if (keyEvent->key() == Qt::Key_Tab && m_modeStatus == SessionBaseModel::ShutDownMode) { if (m_systemMonitor && m_systemMonitor->isVisible() && m_currentSelectedBtn && m_currentSelectedBtn->isVisible()) { if (m_currentSelectedBtn->isChecked()) { m_currentSelectedBtn->setChecked(false); @@ -523,7 +669,16 @@ bool ShutdownWidget::eventFilter(QObject *watched, QEvent *event) } return true; } + } else if (event->type() == QEvent::FocusOut && m_currentSelectedBtn && m_currentSelectedBtn->isVisible() && m_modeStatus != SessionBaseModel::ShutDownMode) { + m_currentSelectedBtn->setChecked(false); + } else if (event->type() == QEvent::FocusIn && m_currentSelectedBtn && m_currentSelectedBtn->isVisible() && m_modeStatus != SessionBaseModel::ShutDownMode) { + m_currentSelectedBtn->setChecked(true); + } + + if (event->type() == QEvent::Hide && m_modeStatus == SessionBaseModel::PowerMode) { + m_currentSelectedBtn = m_requireShutdownButton; } + return false; } @@ -553,16 +708,9 @@ bool ShutdownWidget::event(QEvent *e) for (auto it = m_trList.constBegin(); it != m_trList.constEnd(); ++it) { it->first(qApp->translate("ShutdownWidget", it->second.toUtf8())); } - } - - if (e->type() == QEvent::FocusIn) { - if (m_index < 0) { - m_index = 0; - } - m_frameDataBind->updateValue("ShutdownWidget", m_index); - m_btnList.at(m_index)->updateState(RoundItemButton::Checked); - } else if (e->type() == QEvent::FocusOut) { - m_btnList.at(m_index)->updateState(RoundItemButton::Normal); + } else if (e->type() == QEvent::Hide) { + // 隐藏的时候重置状态,避免下次进入的时候默认选中了更新按钮 + m_model->setUpdatePowerMode(SessionBaseModel::UPM_None); } return QFrame::event(e); @@ -597,6 +745,21 @@ void ShutdownWidget::setModel(SessionBaseModel *const model) connect(model, &SessionBaseModel::canSleepChanged, this, &ShutdownWidget::enableSleepBtn); connect(model, &SessionBaseModel::currentUserChanged, this, &ShutdownWidget::updateLocale); + connect(m_model, &SessionBaseModel::visibleChanged, this, [this](bool visible) { + m_modeStatus = visible? m_modeStatus : SessionBaseModel::ModeStatus::NoStatus; + }); enableSleepBtn(model->canSleep()); } + +void ShutdownWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == "hideLogoutButton" && obj->m_requireLogoutButton + && obj->m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { + obj->m_requireLogoutButton->setVisible(!value.toBool()); + } +} diff --git a/src/widgets/shutdownwidget.h b/src/widgets/shutdownwidget.h index d38c8e53..8036b11f 100644 --- a/src/widgets/shutdownwidget.h +++ b/src/widgets/shutdownwidget.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef SHUTDOWNWIDGET #define SHUTDOWNWIDGET @@ -34,15 +13,8 @@ #include "util_updateui.h" #include "rounditembutton.h" #include "sessionbasemodel.h" -#include "framedatabind.h" -#include "dbuslogin1manager.h" #include "switchos_interface.h" #include "systemmonitor.h" -#include "public_func.h" - -DCORE_BEGIN_NAMESPACE -class DConfig; -DCORE_END_NAMESPACE class ShutdownWidget: public QFrame { @@ -52,7 +24,12 @@ class ShutdownWidget: public QFrame ~ShutdownWidget() override; void setModel(SessionBaseModel * const model); void onStatusChanged(SessionBaseModel::ModeStatus status); +#ifndef ENABLE_DSS_SNIPE bool enableState(const QString &gsettingsValue); +#else + bool enableState(int settingsValue); +#endif + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); public slots: void leftKeySwitch(); @@ -61,7 +38,7 @@ public slots: void recoveryLayout(); void onRequirePowerAction(SessionBaseModel::PowerAction powerAction, bool needConfirm); void setUserSwitchEnable(bool enable); - void onEnable(const QString &gsettingsName, bool enable); + void onEnable(const QString &key, bool enable); void updateLocale(std::shared_ptr user); protected: @@ -74,11 +51,10 @@ public slots: void initUI(); void initConnect(); void updateTr(RoundItemButton * widget, const QString &tr); - void onOtherPageChanged(const QVariant &value); - void hideToplevelWindow(); void enterKeyPushed(); void enableHibernateBtn(bool enable); void enableSleepBtn(bool enable); + void setButtonsVisible(); private: int m_index; @@ -86,14 +62,13 @@ public slots: QList m_btnList; QList, QString>> m_trList; SessionBaseModel* m_model; - FrameDataBind *m_frameDataBind; QFrame* m_shutdownFrame = nullptr; SystemMonitor* m_systemMonitor = nullptr; QFrame* m_actionFrame = nullptr; QStackedLayout* m_mainLayout; QHBoxLayout* m_shutdownLayout; QVBoxLayout* m_actionLayout; - RoundItemButton* m_currentSelectedBtn = nullptr; + RoundItemButton* m_currentSelectedBtn; RoundItemButton* m_requireShutdownButton; RoundItemButton* m_requireRestartButton; RoundItemButton* m_requireSuspendButton; @@ -101,9 +76,11 @@ public slots: RoundItemButton* m_requireLockButton; RoundItemButton* m_requireLogoutButton; RoundItemButton* m_requireSwitchUserBtn; - RoundItemButton* m_requireSwitchSystemBtn = nullptr; - HuaWeiSwitchOSInterface *m_switchosInterface = nullptr; - DTK_CORE_NAMESPACE::DConfig *m_dconfig; + RoundItemButton* m_requireSwitchSystemBtn; + RoundItemButton* m_updateAndShutdownButton; + RoundItemButton* m_updateAndRebootButton; + HuaWeiSwitchOSInterface *m_switchosInterface; + SessionBaseModel::ModeStatus m_modeStatus; }; #endif // SHUTDOWNWIDGET diff --git a/src/widgets/systemmonitor.cpp b/src/widgets/systemmonitor.cpp index 92cf744e..a8ddfef9 100644 --- a/src/widgets/systemmonitor.cpp +++ b/src/widgets/systemmonitor.cpp @@ -1,43 +1,20 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "systemmonitor.h" #include -#include -#include #include +#include DWIDGET_USE_NAMESPACE SystemMonitor::SystemMonitor(QWidget *parent) - : QWidget(parent) + : ActionWidget(parent) , m_icon(new QLabel(this)) , m_text(new QLabel(this)) - , m_state(Leave) { setObjectName(QStringLiteral("SystemMonitor")); setAccessibleName(QStringLiteral("SystemMonitor")); @@ -50,98 +27,14 @@ SystemMonitor::SystemMonitor(QWidget *parent) void SystemMonitor::initUI() { QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->setSpacing(5); - mainLayout->setContentsMargins(10, 0, 10, 0); + mainLayout->setSpacing(10); + mainLayout->setContentsMargins(35, 0, 35, 0); m_icon->setPixmap(DHiDPIHelper::loadNxPixmap(":/img/deepin-system-monitor.svg")); m_text->setText(tr("Start system monitor")); mainLayout->addWidget(m_icon, 0, Qt::AlignVCenter | Qt::AlignRight); mainLayout->addWidget(m_text, 1, Qt::AlignVCenter | Qt::AlignLeft); -} -void SystemMonitor::setState(const State state) -{ - m_state = state; - update(); -} - -void SystemMonitor::enterEvent(QEvent *event) -{ - m_state = Enter; - update(); - - QWidget::enterEvent(event); -} - -void SystemMonitor::leaveEvent(QEvent *event) -{ - m_state = Leave; - update(); - - QWidget::leaveEvent(event); -} - -void SystemMonitor::mouseReleaseEvent(QMouseEvent *event) -{ - m_state = Release; - emit requestShowSystemMonitor(); - update(); - - QWidget::mouseReleaseEvent(event); -} - -void SystemMonitor::mousePressEvent(QMouseEvent *event) -{ - m_state = Press; - update(); - - QWidget::mousePressEvent(event); -} - -void SystemMonitor::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - m_state = Press; - } - update(); - - QWidget::keyReleaseEvent(event); -} - -void SystemMonitor::keyReleaseEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - emit requestShowSystemMonitor(); - m_state = Release; - } - update(); - - QWidget::keyReleaseEvent(event); -} - -void SystemMonitor::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - - painter.setPen(Qt::NoPen); - painter.setRenderHint(QPainter::Antialiasing, true); - - switch (m_state) { - case Enter: - painter.setBrush(QColor(0, 0, 0, 75)); - break; - case Leave: - painter.setBrush(QColor(0, 0, 0, 0)); - break; - case Release: - painter.setBrush(QColor(0, 0, 0, 75)); - break; - case Press: - painter.setBrush(QColor(0, 0, 0, 105)); - break; - } - painter.drawRoundedRect(QRect(1, 1, width() - 2, height() - 2), 10, 10); - - QWidget::paintEvent(event); -} + DFontSizeManager::instance()->bind(m_text, DFontSizeManager::T6); +} \ No newline at end of file diff --git a/src/widgets/systemmonitor.h b/src/widgets/systemmonitor.h index 346b854c..679d8334 100644 --- a/src/widgets/systemmonitor.h +++ b/src/widgets/systemmonitor.h @@ -1,69 +1,28 @@ -/* - * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2011 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef SYSTEMMONITOR_H #define SYSTEMMONITOR_H +#include "actionwidget.h" + #include #include -class SystemMonitor : public QWidget +class SystemMonitor : public ActionWidget { Q_OBJECT public: - enum State { - Enter, - Leave, - Press, - Release - }; explicit SystemMonitor(QWidget *parent = nullptr); - inline State state() { return m_state; } - void setState(const State state); - -signals: - void requestShowSystemMonitor(); - -protected: - void enterEvent(QEvent *event) override; - void leaveEvent(QEvent *event) override; - void mouseReleaseEvent(QMouseEvent *event) override; - void mousePressEvent(QMouseEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void paintEvent(QPaintEvent *event) override; - private: void initUI(); private: QLabel *m_icon; QLabel *m_text; - State m_state; }; #endif // SYSTEMMONITOR_H diff --git a/src/widgets/timewidget.cpp b/src/widgets/timewidget.cpp index 55200d5c..96b2dbf8 100644 --- a/src/widgets/timewidget.cpp +++ b/src/widgets/timewidget.cpp @@ -1,43 +1,25 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "timewidget.h" #include #include #include -#include const QStringList weekdayFormat = {"dddd", "ddd"}; const QStringList shortDateFormat = { "yyyy/M/d", "yyyy-M-d", "yyyy.M.d", "yyyy/MM/dd", "yyyy-MM-dd", "yyyy.MM.dd", - "yy/M/d", "yy-M-d", "yy.M.d" }; + "MM.dd.yyyy", "dd.MM.yyyy", "yy/M/d", + "yy-M-d", "yy.M.d" }; const QStringList shortTimeFormat = { "h:mm", "hh:mm"}; TimeWidget::TimeWidget(QWidget *parent) : QWidget(parent) + , m_timeLabel(nullptr) + , m_dateLabel(nullptr) + , m_refreshTimer(nullptr) , m_use24HourFormat(true) { QFont timeFont; @@ -98,6 +80,13 @@ void TimeWidget::refreshTime() QString date_format = shortDateFormat.at(m_shortDateIndex) + " " + weekdayFormat.at(m_weekdayIndex); m_dateLabel->setText(m_locale.toString(QDateTime::currentDateTime(), date_format)); + +#ifdef ENABLE_DSS_SNIPE + if (!m_shortTimeFormat.isEmpty() && !m_shortDateFormat.isEmpty()) { + m_timeLabel->setText(m_locale.toString(QTime::currentTime(), m_shortTimeFormat)); + m_dateLabel->setText(m_locale.toString(QDate::currentDate(), m_shortDateFormat + " " + weekdayFormat.at(m_weekdayIndex))); + } +#endif // ENABLE_DSS_SNIPE } /** @@ -135,3 +124,21 @@ void TimeWidget::setShortTimeFormat(int type) m_shortTimeIndex = type; refreshTime(); } + +QSize TimeWidget::sizeHint() const +{ + return QSize(QWidget::sizeHint().width(), m_dateLabel->fontMetrics().height() + m_timeLabel->fontMetrics().height()); +} + +#ifdef ENABLE_DSS_SNIPE +void TimeWidget::updateLocale(const QString &locale, const QString &shortTimeFormat, const QString &shortDateFormat) +{ + m_locale = QLocale(locale); + if (!shortTimeFormat.isEmpty()) + m_shortTimeFormat = shortTimeFormat; + if (!shortDateFormat.isEmpty()) + m_shortDateFormat = shortDateFormat; + + refreshTime(); +} +#endif // ENABLE_DSS_SNIPE diff --git a/src/widgets/timewidget.h b/src/widgets/timewidget.h index 898a8ae8..e24dba85 100644 --- a/src/widgets/timewidget.h +++ b/src/widgets/timewidget.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef TIMEWIDGET_H #define TIMEWIDGET_H @@ -42,6 +21,11 @@ class TimeWidget : public QWidget inline bool get24HourFormat() const { return m_use24HourFormat; } void set24HourFormat(bool use24HourFormat); void updateLocale(const QLocale &locale); + QSize sizeHint() const override; + +#ifdef ENABLE_DSS_SNIPE + void updateLocale(const QString &locale, const QString &shortTimeFormat = "", const QString &shortDateFormat = ""); +#endif // ENABLE_DSS_SNIPE public Q_SLOTS: void setWeekdayFormatType(int type); @@ -62,6 +46,11 @@ public Q_SLOTS: int m_weekdayIndex = 0; int m_shortDateIndex = 0; int m_shortTimeIndex = 0; + +#ifdef ENABLE_DSS_SNIPE + QString m_shortTimeFormat; + QString m_shortDateFormat; +#endif // ENABLE_DSS_SNIPE }; #endif // TIMEWIDGET_H diff --git a/src/widgets/tipswidget.cpp b/src/widgets/tipswidget.cpp index 045c6ad9..a5f6b974 100644 --- a/src/widgets/tipswidget.cpp +++ b/src/widgets/tipswidget.cpp @@ -1,16 +1,29 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include #include "tipswidget.h" +#include + DWIDGET_USE_NAMESPACE +DGUI_USE_NAMESPACE TipsWidget::TipsWidget(QWidget *parent) : DArrowRectangle(DArrowRectangle::ArrowBottom, parent) { - setProperty("_d_radius_force", true); // 无特效模式时,让窗口圆角 - setShadowBlurRadius(20); - setRadius(6); + if (DWindowManagerHelper::instance()->hasComposite()) { + setRadiusArrowStyleEnable(true); + setProperty("_d_radius_force", true); + setShadowBlurRadius(20); + setRadius(6); + } else { + setProperty("_d_radius_force", false); + } setShadowYOffset(2); setShadowXOffset(0); - setArrowWidth(18); + setArrowWidth(20); setArrowHeight(10); } @@ -35,7 +48,7 @@ bool TipsWidget::eventFilter(QObject *o, QEvent *e) return false; if (isVisible()) { - QTimer::singleShot(10, this, [=] { + QTimer::singleShot(10, this, [this] { if (isVisible()) show(m_lastPos.x(), m_lastPos.y()); }); diff --git a/src/widgets/tipswidget.h b/src/widgets/tipswidget.h index 1954613c..a534bab4 100644 --- a/src/widgets/tipswidget.h +++ b/src/widgets/tipswidget.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef TIPSWIDGET_H #define TIPSWIDGET_H diff --git a/src/widgets/transparentbutton.cpp b/src/widgets/transparentbutton.cpp new file mode 100644 index 00000000..c7d5c5e2 --- /dev/null +++ b/src/widgets/transparentbutton.cpp @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "transparentbutton.h" + +#include + +TransparentButton::TransparentButton(QWidget *parent) + : DFloatingButton (parent) +{ + +}; + +void TransparentButton::setColor(const QColor &color) +{ + m_color = color; + update(); +} + +void TransparentButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + // 按钮不可用时颜色还是使用活动色,然后需要40%透明 + DStylePainter p(this); + DStyleOptionButton opt; + initStyleOption(&opt); + + if (!m_color.isValid()) { + opt.palette.setBrush(QPalette::Button, qApp->palette().highlight()); + } else { + opt.palette.setBrush(QPalette::Button, m_color); + } + + if (isEnabled()) { + p.setOpacity(1.0); + } else { + p.setOpacity(0.4); + } + + p.drawControl(DStyle::CE_IconButton, opt); +}; diff --git a/src/widgets/transparentbutton.h b/src/widgets/transparentbutton.h new file mode 100644 index 00000000..f8c249dd --- /dev/null +++ b/src/widgets/transparentbutton.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef TRANSPARENTBUTTON_H +#define TRANSPARENTBUTTON_H + +#include + +DWIDGET_USE_NAMESPACE + +class TransparentButton : public DFloatingButton +{ + Q_OBJECT + +public: + explicit TransparentButton(QWidget *parent = nullptr); + + void setColor(const QColor &color); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QColor m_color; +}; + +#endif // TRANSPARENTBUTTON_H diff --git a/src/widgets/user_name_widget.cpp b/src/widgets/user_name_widget.cpp new file mode 100644 index 00000000..c21d4c3f --- /dev/null +++ b/src/widgets/user_name_widget.cpp @@ -0,0 +1,235 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "user_name_widget.h" +#include "public_func.h" +#include "dconfig_helper.h" +#include "constants.h" + +#include +#include + +#include +#include +#include + +const int USER_PIC_HEIGHT = 16; +const QMargins FullNameContentsMargins(10,0,10,0); +const int FullNameLayoutSpace = 8; + +DWIDGET_USE_NAMESPACE +DCORE_USE_NAMESPACE +using namespace DDESESSIONCC; + +UserNameWidget::UserNameWidget(bool respondFontSizeChange, bool showDisplayName, QWidget *parent) + : QWidget(parent) + , m_userPicLabel(nullptr) + , m_fullNameLabel(nullptr) + , m_displayNameLabel(nullptr) + , m_domainUserLabel(nullptr) + , m_showUserName(false) + , m_showDisplayName(showDisplayName) + , m_respondFontSizeChange(respondFontSizeChange) +{ + initialize(); +} + +void UserNameWidget::initialize() +{ + setAccessibleName("UserNameWidget"); + QVBoxLayout *vLayout = new QVBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + vLayout->setContentsMargins(0, 0, 0, 0); +#else + vLayout->setMargin(0); +#endif + vLayout->setSpacing(0); + QHBoxLayout *hLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + hLayout->setContentsMargins(0, 0, 0, 0); +#else + hLayout->setMargin(0); +#endif + hLayout->setContentsMargins(FullNameContentsMargins); + + m_userPicLabel = new DLabel(this); + m_userPicLabel->setAlignment(Qt::AlignVCenter); + QPixmap pixmap = DHiDPIHelper::loadNxPixmap(":/img/user_name.svg"); + pixmap.setDevicePixelRatio(devicePixelRatioF()); + m_userPicLabel->setAccessibleName(QStringLiteral("CapsStateLabel")); + m_userPicLabel->setPixmap(pixmap); + m_userPicLabel->setFixedSize(USER_PIC_HEIGHT, USER_PIC_HEIGHT); + + m_fullNameLabel = new DLabel(this); + m_fullNameLabel->setAlignment(Qt::AlignVCenter); + QPalette palette = m_fullNameLabel->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + m_fullNameLabel->setPalette(palette); + + // 设置字体大小 + bool ok; + int fontSize = DConfigHelper::instance()->getConfig(FULL_NAME_FONT, 5).toInt(&ok); + if (!ok || fontSize < 0 || fontSize > 9 || !m_respondFontSizeChange) fontSize = DFontSizeManager::T6; + DFontSizeManager::instance()->bind(m_fullNameLabel, static_cast(fontSize)); + + QHBoxLayout *displayNameHLayout = new QHBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + displayNameHLayout->setContentsMargins(0, 0, 0, 0); +#else + displayNameHLayout->setMargin(0); +#endif + displayNameHLayout->setSpacing(0); + QPixmap isDomainUserpixmap = QIcon::fromTheme(":/misc/images/domainUser.svg").pixmap(24, 24); + m_domainUserLabel = new DLabel(this); + m_domainUserLabel->setPixmap(isDomainUserpixmap); + m_domainUserLabel->setAlignment(Qt::AlignVCenter); + m_domainUserLabel->setContentsMargins(0, 5, 10, 0); + m_domainUserLabel->setVisible(false); + displayNameHLayout->addStretch(); + displayNameHLayout->addWidget(m_domainUserLabel); + + if (m_showDisplayName) { + m_displayNameLabel = new DLabel(this); + m_displayNameLabel->setAccessibleName(QStringLiteral("NameLabel")); + m_displayNameLabel->setTextFormat(Qt::TextFormat::PlainText); + m_displayNameLabel->setAlignment(Qt::AlignCenter); + m_displayNameLabel->setTextFormat(Qt::TextFormat::PlainText); + DFontSizeManager::instance()->bind(m_displayNameLabel, DFontSizeManager::T2); + palette = m_displayNameLabel->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + m_displayNameLabel->setPalette(palette); + displayNameHLayout->addWidget(m_displayNameLabel); + } + + displayNameHLayout->addStretch(); + vLayout->addLayout(displayNameHLayout); + + vLayout->addLayout(displayNameHLayout); + vLayout->addLayout(hLayout); + hLayout->addStretch(); + hLayout->addWidget(m_userPicLabel); + hLayout->addSpacing(FullNameLayoutSpace); + hLayout->addWidget(m_fullNameLabel); + hLayout->addStretch(); + + setLayout(vLayout); + + m_showUserName = DConfigHelper::instance()->getConfig(SHOW_USER_NAME, false).toBool(); + m_fullNameLabel->setVisible(m_showUserName); + m_userPicLabel->setVisible(m_showUserName); + + DConfigHelper::instance()->bind(this, FULL_NAME_FONT, &UserNameWidget::onDConfigPropertyChanged); + DConfigHelper::instance()->bind(this, SHOW_USER_NAME, &UserNameWidget::onDConfigPropertyChanged); +} + +void UserNameWidget::updateUserName(const QString &userName) +{ + if (userName == m_userNameStr) + return; + + m_userNameStr = userName; + updateUserNameWidget(); + updateDisplayNameWidget(); +} + +void UserNameWidget::updateUserNameWidget() +{ + const int nameWidth = m_fullNameLabel->fontMetrics().boundingRect(m_fullNameStr).width(); + const int labelMaxWidth = width() - FullNameContentsMargins.left() - m_userPicLabel->width() - FullNameLayoutSpace - FullNameContentsMargins.right(); + + if (m_showUserName) { + if (m_fullNameStr.isEmpty()) { + m_fullNameLabel->setVisible(false); + m_userPicLabel->setVisible(false); + } else { + m_fullNameLabel->setVisible(true); + m_userPicLabel->setVisible(true); + } + } + + if (nameWidth > labelMaxWidth) { + const QString &str = m_fullNameLabel->fontMetrics().elidedText(m_fullNameStr, Qt::ElideRight, labelMaxWidth); + m_fullNameLabel->setText(str); + } else { + m_fullNameLabel->setText(m_fullNameStr); + } +} + +void UserNameWidget::updateFullName(const QString &fullName) +{ + if (fullName == m_fullNameStr) + return; + + m_fullNameStr = fullName; + updateUserNameWidget(); + updateDisplayNameWidget(); +} + +void UserNameWidget::setDomainUserVisible(const bool visible) +{ + m_domainUserLabel->setVisible(visible); +} + +/** + * @brief 如果在DConfig中配置了showUserName为true,那么displayName显示用户名, + * 否则显示全名,如果全名为空,则显示用户名 + * + */ +void UserNameWidget::updateDisplayNameWidget() +{ + if (!m_displayNameLabel) + return; + + QString displayName = m_showUserName ? m_userNameStr : (m_fullNameStr.isEmpty() ? m_userNameStr : m_fullNameStr); + int nameWidth = m_displayNameLabel->fontMetrics().boundingRect(displayName).width(); + int labelMaxWidth = width() - 20; + + if (nameWidth > labelMaxWidth) { + QString str = m_displayNameLabel->fontMetrics().elidedText(displayName, Qt::ElideRight, labelMaxWidth); + m_displayNameLabel->setText(str); + } else { + m_displayNameLabel->setText(displayName); + } +} + +void UserNameWidget::resizeEvent(QResizeEvent *event) +{ + updateUserNameWidget(); + updateDisplayNameWidget(); + + QWidget::resizeEvent(event); +} + +int UserNameWidget::heightHint() const +{ + int height = 0; + if (m_showUserName) + height += qMax(USER_PIC_HEIGHT, m_fullNameLabel->fontMetrics().height()); + if (m_showDisplayName) + height += m_displayNameLabel->fontMetrics().height(); + + return height; +} + +void UserNameWidget::onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr) +{ + auto obj = qobject_cast(objPtr); + if (!obj) + return; + + if (key == SHOW_USER_NAME) { + obj->m_showUserName = value.toBool(); + obj->m_fullNameLabel->setVisible(obj->m_showUserName); + obj->m_userPicLabel->setVisible(obj->m_showUserName); + obj->updateUserNameWidget(); + obj->updateDisplayNameWidget(); + } else if (key == FULL_NAME_FONT && obj->m_respondFontSizeChange) { + bool ok; + const int fontSize = value.toInt(&ok); + if (ok && fontSize > 0 && fontSize < 9) + DFontSizeManager::instance()->bind(obj->m_fullNameLabel, static_cast(fontSize)); + else + qCWarning(DDE_SHELL) << "Top tip text font format error, font size: " << fontSize; + } +} diff --git a/src/widgets/user_name_widget.h b/src/widgets/user_name_widget.h new file mode 100644 index 00000000..5a3104a3 --- /dev/null +++ b/src/widgets/user_name_widget.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dconfig_helper.h" + +#include +#include + +#include + +class UserNameWidget : public QWidget +{ + Q_OBJECT + +public: + explicit UserNameWidget(bool respondFontSizeChange, bool showDisplayName, QWidget *parent = nullptr); + void initialize(); + void updateUserName(const QString &userName); + void updateFullName(const QString &displayName); + void setDomainUserVisible(const bool visible); + int heightHint() const; + void resizeEvent(QResizeEvent *event) override; + static void onDConfigPropertyChanged(const QString &key, const QVariant &value, QObject *objPtr); + +private: + void updateUserNameWidget(); + void updateDisplayNameWidget(); + +private: + Dtk::Widget::DLabel *m_userPicLabel; // 小人儿图标 + Dtk::Widget::DLabel *m_fullNameLabel; // 用户名 + Dtk::Widget::DLabel *m_displayNameLabel; // 用户全名 + Dtk::Widget::DLabel *m_domainUserLabel; // 域账户标识 + bool m_showUserName; // 是否显示账户名,记录DConfig的配置 + bool m_showDisplayName; // 是否显示全名 + QString m_fullNameStr; // 全名 + QString m_userNameStr; // 账户名 + bool m_respondFontSizeChange; // 是否响应字体变化 +}; diff --git a/src/widgets/useravatar.cpp b/src/widgets/useravatar.cpp index d803deeb..6a652d85 100644 --- a/src/widgets/useravatar.cpp +++ b/src/widgets/useravatar.cpp @@ -1,30 +1,9 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include "useravatar.h" -#include "dthememanager.h" + #include #include #include @@ -32,8 +11,6 @@ UserAvatar::UserAvatar(QWidget *parent, bool deleteable) : QPushButton(parent) , m_deleteable(deleteable) - , m_showAnimation(nullptr) - , m_hideAnimation(nullptr) { setGeometry(0, 0, AvatarLargeSize, AvatarLargeSize); @@ -212,7 +189,6 @@ void UserAvatar::setBorderColor(const QColor &borderColor) //} //void UserAvatar::showUserAvatar() { -// qDebug() << "UserAvatar" << "showButton"; // showButton(); //} diff --git a/src/widgets/useravatar.h b/src/widgets/useravatar.h index b63d52d1..67e25eac 100644 --- a/src/widgets/useravatar.h +++ b/src/widgets/useravatar.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef USERAVATAR_H #define USERAVATAR_H @@ -37,13 +16,6 @@ #include -//class AvatarDeleteButton : public DImageButton -//{ -// Q_OBJECT -//public: -// AvatarDeleteButton(QWidget *parent = 0); -//}; - class UserAvatar : public QPushButton { Q_OBJECT @@ -98,7 +70,6 @@ class UserAvatar : public QPushButton QImage imageToGray(const QImage &image); void initDeleteButton(); -// AvatarDeleteButton *m_deleteButton = NULL; QLabel *m_iconLabel = nullptr; QString m_iconPath = ""; QColor m_borderColor; @@ -114,8 +85,6 @@ class UserAvatar : public QPushButton const int AVATAR_ROUND_RADIUS = 18; QPalette m_palette; - QPropertyAnimation *m_showAnimation; - QPropertyAnimation *m_hideAnimation; }; diff --git a/src/widgets/userbutton.cpp b/src/widgets/userbutton.cpp index 2522444d..c1bf8e44 100644 --- a/src/widgets/userbutton.cpp +++ b/src/widgets/userbutton.cpp @@ -1,32 +1,9 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include -#include #include -#include #include "dhidpihelper.h" #include "userbutton.h" @@ -57,7 +34,7 @@ void UserButton::initConnect() #endif connect(m_userAvatar, &UserAvatar::clicked, this, &UserButton::click); connect(m_user.get(), &User::displayNameChanged, m_userNameLabel, &QLabel::setText); - connect(m_user.get(), &User::avatarChanged, this, [=] (const QString avatar) { + connect(m_user.get(), &User::avatarChanged, this, [this](const QString &avatar) { m_userAvatar->setIcon(avatar); }); connect(m_user.get(), &User::loginStateChanged, m_checkedMark, &QLabel::setVisible); @@ -100,14 +77,22 @@ void UserButton::initUI() m_nameLayout = new QHBoxLayout; m_nameLayout->setSpacing(5); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_nameLayout->setContentsMargins(0, 0, 0, 0); +#else m_nameLayout->setMargin(0); +#endif m_nameLayout->addStretch(); m_nameLayout->addWidget(m_checkedMark); m_nameLayout->addWidget(m_userNameLabel); m_nameLayout->addStretch(); m_centralLayout = new QVBoxLayout; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + m_centralLayout->setContentsMargins(0, 0, 0, 0); +#else m_centralLayout->setMargin(0); +#endif m_centralLayout->setSpacing(0); m_centralLayout->addWidget(m_userAvatar); m_centralLayout->setAlignment(m_userAvatar, Qt::AlignHCenter); diff --git a/src/widgets/userbutton.h b/src/widgets/userbutton.h index 4f9856f3..1957d5e1 100644 --- a/src/widgets/userbutton.h +++ b/src/widgets/userbutton.h @@ -1,45 +1,25 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef USERBUTTON_H #define USERBUTTON_H -#include #include -#include -#include -#include -#include -#include -#include -#include +#include + #include #include "useravatar.h" +#ifndef ENABLE_DSS_SNIPE +#include using UserInter = com::deepin::daemon::accounts::User; +#else +#include "userinterface.h" + +using UserInter = org::deepin::dde::accounts1::User; +#endif static const int USER_ICON_WIDTH = 180; static const int USER_ICON_HEIGHT = 180; @@ -95,12 +75,9 @@ public slots: UserAvatar* m_userAvatar; QLabel* m_userNameLabel; QLabel *m_checkedMark; - QHBoxLayout* m_buttonLayout; QHBoxLayout *m_nameLayout; QVBoxLayout* m_centralLayout; - int m_borderWidth = 0; - double m_opacity; #ifndef DISABLE_ANIMATIONS diff --git a/src/widgets/virtualkbinstance.cpp b/src/widgets/virtualkbinstance.cpp index cb8554c0..8ee548e4 100644 --- a/src/widgets/virtualkbinstance.cpp +++ b/src/widgets/virtualkbinstance.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "virtualkbinstance.h" #include @@ -33,7 +37,7 @@ void VirtualKBInstance::init() if (!m_virtualKBProcess) { m_virtualKBProcess = new QProcess(this); - connect(m_virtualKBProcess, &QProcess::readyReadStandardOutput, [ = ]{ + connect(m_virtualKBProcess, &QProcess::readyReadStandardOutput, [this]{ //启动完成onborad进程后,获取onborad主界面,将主界面显示在锁屏界面上 QByteArray output = m_virtualKBProcess->readAllStandardOutput(); @@ -46,7 +50,7 @@ void VirtualKBInstance::init() m_virtualKBWidget->setFixedSize(600, 200); m_virtualKBWidget->hide(); - QTimer::singleShot(300, [=] { + QTimer::singleShot(300, [this] { emit initFinished(); }); }); @@ -61,7 +65,10 @@ void VirtualKBInstance::stopVirtualKBProcess() //结束onborad进程 if (m_virtualKBProcess) { m_virtualKBProcess->close(); - m_virtualKBWidget = nullptr; + if (m_virtualKBWidget) { + delete m_virtualKBWidget; + m_virtualKBWidget = nullptr; + } } } diff --git a/src/widgets/virtualkbinstance.h b/src/widgets/virtualkbinstance.h index 26f15140..699eead6 100644 --- a/src/widgets/virtualkbinstance.h +++ b/src/widgets/virtualkbinstance.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef VIRTUALKBINSTANCE_H #define VIRTUALKBINSTANCE_H diff --git a/src/widgets/warningcontent.cpp b/src/widgets/warningcontent.cpp index f3c8b3bf..c9cc3146 100644 --- a/src/widgets/warningcontent.cpp +++ b/src/widgets/warningcontent.cpp @@ -1,37 +1,26 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "dconfig_helper.h" #include "warningcontent.h" +#include "fullscreenbackground.h" +#include "lockcontent.h" +#include "keyboardmonitor.h" -WarningContent::WarningContent(SessionBaseModel * const model, const SessionBaseModel::PowerAction action, QWidget *parent) +#include + +#include "dbusconstant.h" + +WarningContent::WarningContent(QWidget *parent) : SessionBaseWindow(parent) - , m_model(model) + , m_model(nullptr) , m_login1Inter(new DBusLogin1Manager("org.freedesktop.login1", "/org/freedesktop/login1", QDBusConnection::systemBus(), this)) - , m_powerAction(action) + , m_powerAction(SessionBaseModel::PowerAction::None) + , m_failures(0) { - m_inhibitorBlacklists << "NetworkManager" << "ModemManager" << "com.deepin.daemon.Power"; + setAccessibleName("WarningContent"); + m_inhibitorBlacklists << "NetworkManager" << "ModemManager" << DSS_DBUS::sessionPowerService; setTopFrameVisible(false); setBottomFrameVisible(false); } @@ -41,25 +30,45 @@ WarningContent::~WarningContent() } +WarningContent *WarningContent::instance() +{ + static WarningContent *warningContent = nullptr; + if (!warningContent) { + warningContent = new WarningContent; + } + + return warningContent; +} + +void WarningContent::setModel(SessionBaseModel * const model) +{ + m_model = model; + connect(m_model, &SessionBaseModel::shutdownInhibit, this, &WarningContent::shutdownInhibit); +} + QList WarningContent::listInhibitors(const SessionBaseModel::PowerAction action) { + std::shared_ptr currentUser = m_model->currentUser(); + if (!currentUser) + return QList(); + QList inhibitorList; if (m_login1Inter->isValid()) { - qDebug() << "m_login1Inter is valid!"; - QDBusPendingReply reply = m_login1Inter->ListInhibitors(); reply.waitForFinished(); if (!reply.isError()) { InhibitorsList inhibitList = qdbus_cast(reply.argumentAt(0)); - qDebug() << "inhibitList:" << inhibitList.count(); + qCDebug(DDE_SHELL) << "Inhibitors list count: " << inhibitList.count(); QString type; switch (action) { case SessionBaseModel::PowerAction::RequireShutdown: + case SessionBaseModel::PowerAction::RequireUpdateShutdown: case SessionBaseModel::PowerAction::RequireRestart: + case SessionBaseModel::PowerAction::RequireUpdateRestart: case SessionBaseModel::PowerAction::RequireSwitchSystem: case SessionBaseModel::PowerAction::RequireLogout: type = "shutdown"; @@ -72,16 +81,28 @@ QList WarningContent::listInhibitors(const Sessi return {}; } + QStringList delayInhibitIgnoreList = DConfigHelper::instance()->getConfig("delayInhibitIgnoreList", QStringList()).toStringList(); + for (int i = 0; i < inhibitList.count(); i++) { // Just take care of DStore's inhibition, ignore others'. const Inhibit &inhibitor = inhibitList.at(i); + if (inhibitor.uid != currentUser->uid() && inhibitor.uid != 0) + continue; + +#ifndef ENABLE_DSS_SNIPE if (inhibitor.what.split(':', QString::SkipEmptyParts).contains(type) +#else + if (inhibitor.what.split(':', Qt::SkipEmptyParts).contains(type) +#endif && !m_inhibitorBlacklists.contains(inhibitor.who)) { // 待机时,非block暂不处理,因为目前没有倒计时待机功能 if (type == "sleep" && inhibitor.mode != "block") continue; + if (inhibitor.mode == "delay" && delayInhibitIgnoreList.contains(inhibitor.who)) + continue; + InhibitWarnView::InhibitorData inhibitData; inhibitData.who = inhibitor.who; inhibitData.why = inhibitor.why; @@ -99,7 +120,7 @@ QList WarningContent::listInhibitors(const Sessi if (connection.interface()->isServiceRegistered(inhibitor.who)) { - QDBusInterface ifc(inhibitor.who, "/com/deepin/InhibitHint", "com.deepin.InhibitHint", connection); + QDBusInterface ifc(inhibitor.who, DSS_DBUS::inhibitHintPath, DSS_DBUS::inhibitHintService, connection); QDBusMessage msg = ifc.call("Get", qgetenv("LANG"), inhibitor.why); if (msg.type() == QDBusMessage::ReplyMessage) { InhibitHint inhibitHint = qdbus_cast(msg.arguments().at(0).value()); @@ -116,20 +137,17 @@ QList WarningContent::listInhibitors(const Sessi } } - qDebug() << "List of valid '" << type << "' inhibitors:"; - for (const InhibitWarnView::InhibitorData &data : inhibitorList) { - qDebug() << "who:" << data.who; - qDebug() << "why:" << data.why; - qDebug() << "pid:" << data.pid; + qCDebug(DDE_SHELL) << "Inhibitor list detail: who:" << data.who + << ", why:" << data.why + << ", pid:" << data.pid; } - qDebug() << "End list inhibitor"; } else { - qWarning() << "D-Bus request reply error:" << reply.error().message(); + qCWarning(DDE_SHELL) << "DBus request reply error:" << reply.error().message(); } } else { - qWarning() << "shutdown login1Manager error!"; + qCWarning(DDE_SHELL) << "Login1 interface is invalid"; } return inhibitorList; @@ -137,21 +155,60 @@ QList WarningContent::listInhibitors(const Sessi void WarningContent::doCancelShutdownInhibit() { - if (m_model->isCheckedInhibit()) return; + InhibitWarnView *view = qobject_cast(m_warningView); + if (view && view->delayView()) + return; - m_model->setIsCheckedInhibit(true); + qCInfo(DDE_SHELL) << "Cancel shutdown inhibit"; m_model->setPowerAction(SessionBaseModel::PowerAction::None); - emit m_model->cancelShutdownInhibit(); + FullScreenBackground::setContent(LockContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::LockContent); + // 从lock点的power btn,不能隐藏锁屏而进入桌面 + if (m_model->currentModeState() == SessionBaseModel::ModeStatus::ShutDownMode) { + m_model->setVisible(false); + m_model->setCurrentModeState(SessionBaseModel::PasswordMode); + } } -void WarningContent::doAccecpShutdownInhibit() +void WarningContent::doAcceptShutdownInhibit() { - if (m_model->isCheckedInhibit()) return; + qCInfo(DDE_SHELL) << "Accept shutdown inhibit, power action: " << m_powerAction + << ", current mode: " << m_model->currentModeState(); + InhibitWarnView *view = qobject_cast(sender()); + if (view) { + view->setDelayView(false); + if (view->hasInhibit()) { + switch (m_powerAction) { + case SessionBaseModel::PowerAction::RequireShutdown: + case SessionBaseModel::PowerAction::RequireUpdateShutdown: + view->setDelayView(true); + view->setInhibitConfirmMessage(tr("Closing the programs and shutting down, please wait..."), true); + break; + case SessionBaseModel::PowerAction::RequireRestart: + case SessionBaseModel::PowerAction::RequireUpdateRestart: + view->setDelayView(true); + view->setInhibitConfirmMessage(tr("Closing the programs and rebooting, please wait..."), true); + break; + case SessionBaseModel::PowerAction::RequireLogout: + view->setDelayView(true); + view->setInhibitConfirmMessage(tr("Closing the programs and logging out, please wait..."), true); + break; + default: + break; + } + } + } - m_model->setIsCheckedInhibit(true); m_model->setPowerAction(m_powerAction); - if (m_model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode) - emit m_model->cancelShutdownInhibit(); + + if (m_model->currentModeState() != SessionBaseModel::ModeStatus::ShutDownMode + && m_model->currentModeState() != SessionBaseModel::ModeStatus::PowerMode + && m_powerAction != SessionBaseModel::RequireUpdateShutdown + && m_powerAction != SessionBaseModel::RequireUpdateRestart + && ((m_powerAction == SessionBaseModel::RequireShutdown || m_powerAction == SessionBaseModel::RequireRestart) && m_model->gsCheckpwd())) { + FullScreenBackground::setContent(LockContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::LockContent); + } } void WarningContent::beforeInvokeAction(bool needConfirm) @@ -160,6 +217,7 @@ void WarningContent::beforeInvokeAction(bool needConfirm) const QList> &loginUsers = m_model->loginedUserList(); if (m_warningView != nullptr) { + qCInfo(DDE_SHELL) << "Before invoke action, delete warning view: " << m_warningView; m_warningView->deleteLater(); m_warningView = nullptr; } @@ -167,17 +225,17 @@ void WarningContent::beforeInvokeAction(bool needConfirm) // change ui if (!inhibitors.isEmpty()) { InhibitWarnView *view = new InhibitWarnView(m_powerAction, this); - view->setFocusPolicy(Qt::StrongFocus); - setFocusPolicy(Qt::NoFocus); view->setInhibitorList(inhibitors); switch (m_powerAction) { case SessionBaseModel::PowerAction::RequireShutdown: + case SessionBaseModel::PowerAction::RequireUpdateShutdown: view->setInhibitConfirmMessage(tr("The programs are preventing the computer from shutting down, and forcing shut down may cause data loss.") + "\n" + tr("To close the program, click Cancel, and then close the program.")); break; case SessionBaseModel::PowerAction::RequireSwitchSystem: case SessionBaseModel::PowerAction::RequireRestart: + case SessionBaseModel::PowerAction::RequireUpdateRestart: view->setInhibitConfirmMessage(tr("The programs are preventing the computer from reboot, and forcing reboot may cause data loss.") + "\n" + tr("To close the program, click Cancel, and then close the program.")); break; @@ -204,7 +262,8 @@ void WarningContent::beforeInvokeAction(bool needConfirm) if (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown) { view->setAcceptReason(tr("Shut down")); view->setAcceptVisible(!isBlock); - } else if (m_powerAction == SessionBaseModel::PowerAction::RequireRestart || m_powerAction == SessionBaseModel::PowerAction::RequireSwitchSystem) { + } else if (m_powerAction == SessionBaseModel::PowerAction::RequireRestart + || m_powerAction == SessionBaseModel::PowerAction::RequireSwitchSystem) { view->setAcceptReason(tr("Reboot")); view->setAcceptVisible(!isBlock); } else if (m_powerAction == SessionBaseModel::PowerAction::RequireSuspend) { @@ -216,19 +275,30 @@ void WarningContent::beforeInvokeAction(bool needConfirm) } else if (m_powerAction == SessionBaseModel::PowerAction::RequireLogout) { view->setAcceptReason(tr("Log out")); view->setAcceptVisible(!isBlock); + } else if (m_powerAction == SessionBaseModel::PowerAction::RequireUpdateShutdown) { + view->setAcceptReason(tr("Update and Shut Down")); + view->setAcceptVisible(!isBlock); + } else if (m_powerAction == SessionBaseModel::PowerAction::RequireUpdateRestart) { + view->setAcceptReason(tr("Update and Reboot")); + view->setAcceptVisible(!isBlock); } m_warningView = view; - m_warningView->setFixedSize(getCenterContentSize()); setCenterContent(m_warningView); + qCInfo(DDE_SHELL) << "Before invoke action, warning view: " << m_warningView; + connect(view, &InhibitWarnView::cancelled, this, &WarningContent::doCancelShutdownInhibit); - connect(view, &InhibitWarnView::actionInvoked, this, &WarningContent::doAccecpShutdownInhibit); + connect(view, &InhibitWarnView::actionInvoked, this, &WarningContent::doAcceptShutdownInhibit); return; } - if (loginUsers.length() > 1 && (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown || m_powerAction == SessionBaseModel::PowerAction::RequireRestart)) { + if (loginUsers.length() > 1 + && (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown + || m_powerAction == SessionBaseModel::PowerAction::RequireRestart + || m_powerAction == SessionBaseModel::PowerAction::RequireUpdateShutdown + || m_powerAction == SessionBaseModel::PowerAction::RequireUpdateRestart)) { QList> tmpList = loginUsers; for (auto it = tmpList.begin(); it != tmpList.end();) { @@ -240,20 +310,22 @@ void WarningContent::beforeInvokeAction(bool needConfirm) } MultiUsersWarningView *view = new MultiUsersWarningView(m_powerAction, this); - view->setFocusPolicy(Qt::StrongFocus); - setFocusPolicy(Qt::NoFocus); view->setUsers(tmpList); if (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown) view->setAcceptReason(tr("Shut down")); else if (m_powerAction == SessionBaseModel::PowerAction::RequireRestart) view->setAcceptReason(tr("Reboot")); + else if (m_powerAction == SessionBaseModel::PowerAction::RequireUpdateRestart) + view->setAcceptReason(tr("Update and Reboot")); + else if (m_powerAction == SessionBaseModel::PowerAction::RequireUpdateShutdown) + view->setAcceptReason(tr("Update and Shut Down")); m_warningView = view; m_warningView->setFixedSize(getCenterContentSize()); setCenterContent(m_warningView); connect(view, &MultiUsersWarningView::cancelled, this, &WarningContent::doCancelShutdownInhibit); - connect(view, &MultiUsersWarningView::actionInvoked, this, &WarningContent::doAccecpShutdownInhibit); + connect(view, &MultiUsersWarningView::actionInvoked, this, &WarningContent::doAcceptShutdownInhibit); return; } @@ -262,12 +334,12 @@ void WarningContent::beforeInvokeAction(bool needConfirm) m_powerAction == SessionBaseModel::PowerAction::RequireRestart || m_powerAction == SessionBaseModel::PowerAction::RequireLogout)) { InhibitWarnView *view = new InhibitWarnView(m_powerAction, this); - view->setFocusPolicy(Qt::StrongFocus); - setFocusPolicy(Qt::NoFocus); - if (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown) { + if (m_powerAction == SessionBaseModel::PowerAction::RequireShutdown + || m_powerAction == SessionBaseModel::PowerAction::RequireUpdateShutdown) { view->setAcceptReason(tr("Shut down")); view->setInhibitConfirmMessage(tr("Are you sure you want to shut down?")); - } else if (m_powerAction == SessionBaseModel::PowerAction::RequireRestart) { + } else if (m_powerAction == SessionBaseModel::PowerAction::RequireRestart + || m_powerAction == SessionBaseModel::PowerAction::RequireUpdateRestart) { view->setAcceptReason(tr("Reboot")); view->setInhibitConfirmMessage(tr("Are you sure you want to reboot?")); } else if (m_powerAction == SessionBaseModel::PowerAction::RequireLogout) { @@ -280,21 +352,93 @@ void WarningContent::beforeInvokeAction(bool needConfirm) setCenterContent(m_warningView); connect(view, &InhibitWarnView::cancelled, this, &WarningContent::doCancelShutdownInhibit); - connect(view, &InhibitWarnView::actionInvoked, this, &WarningContent::doAccecpShutdownInhibit); + connect(view, &InhibitWarnView::actionInvoked, this, &WarningContent::doAcceptShutdownInhibit); + + return; + } + + doAcceptShutdownInhibit(); +} + +/** + * @brief 抓取键盘,失败后继续抓取,最多尝试15次. + * + * @param exitIfFailed true: 发送失败通知,并隐藏锁屏。 false:不做任何处理。 + */ +void WarningContent::tryGrabKeyboard(bool exitIfFailed) +{ +#ifndef QT_DEBUG + if (!isVisible()) { + return; + } + + if (m_model->isUseWayland()) { + static QDBusInterface *kwinInter = new QDBusInterface("org.kde.KWin","/KWin","org.kde.KWin", QDBusConnection::sessionBus()); + if (!kwinInter || !kwinInter->isValid()) { + qCWarning(DDE_SHELL) << "Kwin interface is invalid"; + m_failures = 0; + return; + } + // wayland下判断是否有应用发起grab,如果有就不锁屏 + QDBusReply reply = kwinInter->call("xwaylandGrabed"); + if (!reply.isValid() || !reply.value()) { + m_failures = 0; + return; + } + } else { + if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(true)) { + m_failures = 0; + return; + } + } + + if (m_failures > 5) { + qCWarning(DDE_SHELL) << "Trying ungrab keyboard in warning content"; + KeyboardMonitor::instance()->ungrabKeyboard(); + } + + m_failures++; + + if (m_failures == 15) { + qCWarning(DDE_SHELL) << "Trying to grab keyboard has exceeded the upper limit. dde-lock will quit."; + + m_failures = 0; + + if (!exitIfFailed) { + return; + } + qCInfo(DDE_SHELL) << "Request hide lock frame"; + emit requestLockFrameHide(); return; } - doAccecpShutdownInhibit(); + QTimer::singleShot(100, this, [this, exitIfFailed] { + tryGrabKeyboard(exitIfFailed); + }); +#endif +} + +void WarningContent::showEvent(QShowEvent *event) +{ + tryGrabKeyboard(); + QFrame::showEvent(event); } void WarningContent::setPowerAction(const SessionBaseModel::PowerAction action) { if (m_powerAction == action) return; + m_powerAction = action; } +bool WarningContent::supportDelayOrWait() const +{ + InhibitWarnView *view = qobject_cast(m_warningView); + return (view && view->hasInhibit() && view->delayView()); +} + void WarningContent::mouseReleaseEvent(QMouseEvent *event) { doCancelShutdownInhibit(); @@ -310,3 +454,13 @@ void WarningContent::keyPressEvent(QKeyEvent *event) } QWidget::keyPressEvent(event); } + +void WarningContent::shutdownInhibit(const SessionBaseModel::PowerAction action, bool needConfirm) +{ + qCInfo(DDE_SHELL) << "Shutdown inhibit, action: " << action; + setPowerAction(action); + //检查是否允许关机 + FullScreenBackground::setContent(WarningContent::instance()); + m_model->setCurrentContentType(SessionBaseModel::WarningContent); + beforeInvokeAction(needConfirm); +} diff --git a/src/widgets/warningcontent.h b/src/widgets/warningcontent.h index bbb841dd..bb705626 100644 --- a/src/widgets/warningcontent.h +++ b/src/widgets/warningcontent.h @@ -1,27 +1,6 @@ -/* - * Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd. - * - * Author: sbw - * kirigaya - * Hualet - * - * Maintainer: sbw - * kirigaya - * Hualet - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef WARNINGCONTENT_H #define WARNINGCONTENT_H @@ -41,17 +20,28 @@ class WarningContent : public SessionBaseWindow Q_OBJECT public: - explicit WarningContent(SessionBaseModel *const model, const SessionBaseModel::PowerAction action, QWidget *parent = nullptr); + explicit WarningContent(QWidget *parent = nullptr); ~WarningContent() override; + static WarningContent *instance(); + void setModel(SessionBaseModel * const model); void beforeInvokeAction(bool needConfirm); void setPowerAction(const SessionBaseModel::PowerAction action); + bool supportDelayOrWait() const; + void tryGrabKeyboard(bool exitIfFailed = true); + +signals: + void requestLockFrameHide(); protected: void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; QList listInhibitors(const SessionBaseModel::PowerAction action); void doCancelShutdownInhibit(); - void doAccecpShutdownInhibit(); + void doAcceptShutdownInhibit(); + +private slots: + void shutdownInhibit(const SessionBaseModel::PowerAction action, bool needConfirm); private: SessionBaseModel *m_model; @@ -59,6 +49,7 @@ class WarningContent : public SessionBaseWindow WarningView * m_warningView = nullptr; QStringList m_inhibitorBlacklists; SessionBaseModel::PowerAction m_powerAction; + int m_failures; }; class InhibitHint diff --git a/src/widgets/warningview.h b/src/widgets/warningview.h index ef3622ec..911cf8e4 100644 --- a/src/widgets/warningview.h +++ b/src/widgets/warningview.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #ifndef WARNINGVIEW_H #define WARNINGVIEW_H @@ -15,8 +19,6 @@ class WarningView : public QFrame { public: explicit WarningView(QWidget *parent = nullptr) : QFrame(parent) {} - virtual void toggleButtonState() = 0; - virtual void buttonClickHandle() = 0; virtual void setAcceptReason(const QString &reason) = 0; protected: @@ -24,7 +26,6 @@ class WarningView : public QFrame * \brief setCurrentButton 设置当前的按钮 * \param btntype 按钮枚举 */ - virtual void setCurrentButton(const ButtonType btntype) = 0; }; #endif // WARNINGVIEW_H diff --git a/src/widgets/widgetsimages.qrc b/src/widgets/widgetsimages.qrc index d46b99c0..6312470e 100644 --- a/src/widgets/widgetsimages.qrc +++ b/src/widgets/widgetsimages.qrc @@ -124,6 +124,7 @@ img/nopassword_login_hover.svg img/nopassword_login_normal.svg img/logo.svg + img/warning.svg img/bottom_actions/reboot.svg img/bottom_actions/shutdown.svg img/default_avatar.svg @@ -183,5 +184,56 @@ img/list_actions/userswitch_normal.svg img/list_actions/userswitch_press.svg img/deepin-system-monitor.svg + img/back-normal.svg + img/back-hover.svg + img/user_name.svg + img/update/failed.svg + img/update/success.svg + img/update/logo.svg + img/update/waiting_update/waiting_update_0.png + img/update/waiting_update/waiting_update_1.png + img/update/waiting_update/waiting_update_2.png + img/update/waiting_update/waiting_update_3.png + img/update/waiting_update/waiting_update_4.png + img/update/waiting_update/waiting_update_5.png + img/update/waiting_update/waiting_update_6.png + img/update/waiting_update/waiting_update_7.png + img/update/waiting_update/waiting_update_8.png + img/update/waiting_update/waiting_update_9.png + img/update/waiting_update/waiting_update_10.png + img/update/waiting_update/waiting_update_11.png + img/update/waiting_update/waiting_update_12.png + img/update/waiting_update/waiting_update_13.png + img/update/waiting_update/waiting_update_14.png + img/update/waiting_update/waiting_update_15.png + img/update/waiting_update/waiting_update_16.png + img/update/waiting_update/waiting_update_17.png + img/update/waiting_update/waiting_update_18.png + img/update/waiting_update/waiting_update_19.png + img/update/waiting_update/waiting_update_20.png + img/update/waiting_update/waiting_update_21.png + img/update/waiting_update/waiting_update_22.png + img/update/waiting_update/waiting_update_23.png + img/update/waiting_update/waiting_update_24.png + img/update/waiting_update/waiting_update_25.png + img/update/waiting_update/waiting_update_26.png + img/update/waiting_update/waiting_update_27.png + img/update/waiting_update/waiting_update_28.png + img/update/waiting_update/waiting_update_29.png + img/update/waiting_update/waiting_update_30.png + img/update/waiting_update/waiting_update_31.png + img/update/waiting_update/waiting_update_32.png + img/update/waiting_update/waiting_update_33.png + img/update/waiting_update/waiting_update_34.png + img/update/waiting_update/waiting_update_35.png + img/update/waiting_update/waiting_update_36.png + img/update/waiting_update/waiting_update_37.png + img/update/waiting_update/waiting_update_38.png + img/update/waiting_update/waiting_update_39.png + img/inhibitview/cancel_normal.svg + img/inhibitview/cancel_hover.svg + img/inhibitview/reboot_warning.svg + img/inhibitview/logout_warning.svg + img/inhibitview/poweroff_warning.svg diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index dd4356dd..afd94e7b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -find_package(Qt5 COMPONENTS Test DBus REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Test DBus REQUIRED) find_package(GTest REQUIRED) ADD_COMPILE_OPTIONS(-fno-access-control) diff --git a/tests/dde-lock/CMakeLists.txt b/tests/dde-lock/CMakeLists.txt index 82572fa4..83dc4173 100644 --- a/tests/dde-lock/CMakeLists.txt +++ b/tests/dde-lock/CMakeLists.txt @@ -4,20 +4,24 @@ aux_source_directory(. LOCK_TEST) set(LOCK_TEST_SRCS ${LOCK_TEST} - ${authority_DBUS_SCRS} + ${AUTH_DBUS_SCRS} ${GLOBAL_UTILS} ${GLOBAL_UTILS_DBUS} ${GLOBAL_UTILS_KEYBOARDMONITOR} ${WIDGETS} ${SESSION_WIDGETS} - ${haweiswitchos_DBUS_SCRS} + ${SWITCHOS_DBUS_SCRS} ${AUTHENTICATE} + ${DBUS_DATA_TYPES} + ${PLUGIN_MANAGER} ${PROJECT_SOURCE_DIR}/src/dde-lock/lockframe.cpp ${PROJECT_SOURCE_DIR}/src/dde-lock/lockworker.cpp + ${PROJECT_SOURCE_DIR}/src/dde-lock/updateworker.cpp ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus/dbuslockagent.cpp ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus/dbuslockfrontservice.cpp ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus/dbusshutdownagent.cpp ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus/dbusshutdownfrontservice.cpp + ${PROJECT_SOURCE_DIR}/src/global_util/signal_bridge.h ) add_executable(${BIN_NAME} @@ -29,32 +33,38 @@ add_executable(${BIN_NAME} target_include_directories(${BIN_NAME} PUBLIC ${DTKWIDGET_INCLUDE_DIR} ${DTKCORE_INCLUDE_DIR} - ${DFrameworkDBus_INCLUDE_DIRS} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} - ${QGSettings_INCLUDE_DIRS} ${PAM_INCLUDE_DIR} ${XCB_EWMH_INCLUDE_DIRS} - ${Qt5X11Extras_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/src/dde-lock ${PROJECT_SOURCE_DIR}/src/dde-lock/dbus ) +if (DISABLE_DSS_SNIPE) + target_include_directories(${BIN_NAME} PUBLIC + ${DFrameworkDBus_INCLUDE_DIRS} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ${Qt5X11Extras_INCLUDE_DIRS} + ) +endif () target_link_libraries(${BIN_NAME} PRIVATE - ${Qt5Test_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} - ${DtkWidget_LIBRARIES} - ${DtkCore_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5DBus_LIBRARIES} - ${QGSettings_LIBRARIES} + Qt${QT_VERSION_MAJOR}::Test + Dtk${DTK_VERSION_MAJOR}::Widget + Dtk${DTK_VERSION_MAJOR}::Core ${GTEST_LIBRARIES} ${Qt_LIBS} ${PAM_LIBRARIES} ${XCB_EWMH_LIBRARIES} - ${Qt5Concurrent_LIBRARIES} - ${Qt5X11Extras_LIBRARIES} - ${Qt5Network_LIBRARIES} -lpthread -lm + -lcrypto ) +if (DISABLE_DSS_SNIPE) + target_link_libraries(${BIN_NAME} PRIVATE + ${DFrameworkDBus_LIBRARIES} + ${QGSettings_LIBRARIES} + ${Qt5X11Extras_LIBRARIES} + KF5::WaylandClient + ) +endif () diff --git a/tests/dde-lock/main.cpp b/tests/dde-lock/main.cpp index 2549f98d..b867f2bd 100644 --- a/tests/dde-lock/main.cpp +++ b/tests/dde-lock/main.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include #include diff --git a/tests/dde-lock/ut_authmodule.cpp b/tests/dde-lock/ut_authmodule.cpp index ed027a07..c0210b7f 100644 --- a/tests/dde-lock/ut_authmodule.cpp +++ b/tests/dde-lock/ut_authmodule.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "auth_module.h" #include "authcommon.h" @@ -27,7 +31,7 @@ TEST_F(UT_AuthModule, BasicTest) m_authModule->authState(); m_authModule->authType(); m_authModule->setAnimationState(false); - m_authModule->setAuthState(0, "test"); + m_authModule->setAuthState(AuthCommon::AS_Success, "test"); // m_authModule->setAuthState(""); m_authModule->setLimitsInfo(LimitsInfo()); } diff --git a/tests/dde-lock/ut_authsingle.cpp b/tests/dde-lock/ut_authsingle.cpp index 2f142c51..7fddd241 100644 --- a/tests/dde-lock/ut_authsingle.cpp +++ b/tests/dde-lock/ut_authsingle.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "authcommon.h" #include "auth_single.h" @@ -30,7 +34,7 @@ TEST_F(UT_AuthSingle, basic) TEST_F(UT_AuthSingle, AuthResultTest) { - m_authSingle->setAuthState(INT_MAX, "default"); + m_authSingle->setAuthState(AuthCommon::AS_None, "default"); m_authSingle->setAuthState(AuthCommon::AS_Success, "Success"); m_authSingle->setAuthState(AuthCommon::AS_Failure, "Failure"); m_authSingle->setAuthState(AuthCommon::AS_Cancel, "Cancel"); diff --git a/tests/dde-lock/ut_controlwidget.cpp b/tests/dde-lock/ut_controlwidget.cpp index 405d18aa..f791bd51 100644 --- a/tests/dde-lock/ut_controlwidget.cpp +++ b/tests/dde-lock/ut_controlwidget.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "controlwidget.h" #include "sessionbasemodel.h" #include diff --git a/tests/dde-lock/ut_deepinauthframework.cpp b/tests/dde-lock/ut_deepinauthframework.cpp index 35038256..92c1792d 100644 --- a/tests/dde-lock/ut_deepinauthframework.cpp +++ b/tests/dde-lock/ut_deepinauthframework.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "authcommon.h" #include "deepinauthframework.h" @@ -26,7 +30,7 @@ TEST_F(UT_DeepinAuthFramework, PAMTest) { // m_authFramework->CreateAuthenticate("uos"); // m_authFramework->SendToken("123"); -// m_authFramework->DestoryAuthenticate(); +// m_authFramework->DestroyAuthenticate(); } TEST_F(UT_DeepinAuthFramework, DATest) @@ -42,7 +46,7 @@ TEST_F(UT_DeepinAuthFramework, DATest) // m_authFramework->StartAuthentication(UserName, 19, -1); // m_authFramework->SendTokenToAuth(UserName, 1, "123"); // m_authFramework->EndAuthentication(UserName, 19); -// m_authFramework->DestoryAuthController(UserName); +// m_authFramework->DestroyAuthController(UserName); // m_authFramework->GetFuzzyMFA(UserName); // m_authFramework->GetMFAFlag(UserName); diff --git a/tests/dde-lock/ut_fullscreenbackground.cpp b/tests/dde-lock/ut_fullscreenbackground.cpp index 2c216d3f..f9c97018 100644 --- a/tests/dde-lock/ut_fullscreenbackground.cpp +++ b/tests/dde-lock/ut_fullscreenbackground.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "fullscreenbackground.h" #include "sessionbasemodel.h" @@ -11,7 +15,7 @@ class UT_FullscreenBackground : public testing::Test void SetUp() override; void TearDown() override; - FullscreenBackground *m_background; + FullScreenBackground *m_background; SessionBaseModel *m_model; }; @@ -20,7 +24,7 @@ void UT_FullscreenBackground::SetUp() m_model = new SessionBaseModel(); std::shared_ptr user_ptr(new User); m_model->updateCurrentUser(user_ptr); - m_background = new FullscreenBackground(m_model); + m_background = new FullScreenBackground(m_model); } void UT_FullscreenBackground::TearDown() @@ -35,7 +39,6 @@ TEST_F(UT_FullscreenBackground, BasicTest) m_background->setContent(&w); m_background->isPicture("/usr/share/backgrounds/default_background.jpg"); m_background->getLocalFile("/usr/share/backgrounds/default_background.jpg"); - m_background->setContentVisible(true); m_background->contentVisible(); m_background->setEnterEnable(true); m_background->updateBackground("/usr/share/backgrounds/default_background.jpg"); diff --git a/tests/dde-lock/ut_inhibitbutton.cpp b/tests/dde-lock/ut_inhibitbutton.cpp new file mode 100644 index 00000000..65c0c0ef --- /dev/null +++ b/tests/dde-lock/ut_inhibitbutton.cpp @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "inhibitbutton.h" + +#include + +#include + +class UT_InhibitButton : public testing::Test +{ +protected: + void SetUp() override; + void TearDown() override; + + InhibitButton *m_inhibitButton; +}; + +void UT_InhibitButton::SetUp() +{ + m_inhibitButton = new InhibitButton(nullptr); +} + +void UT_InhibitButton::TearDown() +{ + delete m_inhibitButton; +} + +TEST_F(UT_InhibitButton, BasicTest) { + QString test = "test"; + m_inhibitButton->setText(test); + ASSERT_EQ(test, m_inhibitButton->text()); + + QIcon icon = QIcon::fromTheme(":/img/inhibitview/shutdown.svg"); + m_inhibitButton->setNormalPixmap(icon.pixmap(30, 30)); + ASSERT_FALSE(m_inhibitButton->normalPixmap().isNull()); + m_inhibitButton->setHoverPixmap(icon.pixmap(30, 30)); + ASSERT_FALSE(m_inhibitButton->hoverPixmap().isNull()); +} diff --git a/tests/dde-lock/ut_inhibitwarnview.cpp b/tests/dde-lock/ut_inhibitwarnview.cpp index 239e027b..370eb7ff 100644 --- a/tests/dde-lock/ut_inhibitwarnview.cpp +++ b/tests/dde-lock/ut_inhibitwarnview.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "inhibitwarnview.h" #include @@ -53,10 +57,5 @@ TEST_F(UT_InhibitWarnView, BasicTest) m_inhibitWarnView->setInhibitConfirmMessage("test"); m_inhibitWarnView->setAcceptReason("test"); m_inhibitWarnView->setAcceptVisible(false); - m_inhibitWarnView->toggleButtonState(); - m_inhibitWarnView->buttonClickHandle(); - m_inhibitWarnView->inhibitType(); - m_inhibitWarnView->focusNextPrevChild(false); - m_inhibitWarnView->setCurrentButton(ButtonType::Cancel); QTest::keyPress(m_inhibitWarnView, Qt::Key_Return, Qt::KeyboardModifier::NoModifier); } diff --git a/tests/dde-lock/ut_interface.cpp b/tests/dde-lock/ut_interface.cpp index 9d22b50b..729ac38d 100644 --- a/tests/dde-lock/ut_interface.cpp +++ b/tests/dde-lock/ut_interface.cpp @@ -1,25 +1,10 @@ -/* - * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include +#include "dbusconstant.h" #include "userinfo.h" class UT_Interface : public testing::Test @@ -41,7 +26,7 @@ void UT_Interface::TearDown() TEST_F(UT_Interface, user) { - std::shared_ptr nativeUser(new NativeUser("/com/deepin/daemon/Accounts/User"+QString::number((getuid())))); + std::shared_ptr nativeUser(new NativeUser(QString(DSS_DBUS::accountsUserPath).arg(QString::number(getuid())))); // ASSERT_TRUE(nativeUser->userInter()); // EXPECT_TRUE(nativeUser->userInter()->greeterBackground().isEmpty()); // EXPECT_TRUE(nativeUser->userInter()->uid().isEmpty()); diff --git a/tests/dde-lock/ut_kblayoutwidget.cpp b/tests/dde-lock/ut_kblayoutwidget.cpp index 1798af44..5800ae30 100644 --- a/tests/dde-lock/ut_kblayoutwidget.cpp +++ b/tests/dde-lock/ut_kblayoutwidget.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "kblayoutlistview.h" #include diff --git a/tests/dde-lock/ut_keyboardplantformwayland.cpp b/tests/dde-lock/ut_keyboardplantformwayland.cpp index 3355c6a9..92b612f9 100644 --- a/tests/dde-lock/ut_keyboardplantformwayland.cpp +++ b/tests/dde-lock/ut_keyboardplantformwayland.cpp @@ -1,19 +1,24 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "keyboardplantform_wayland.h" #include +#ifdef USE_DEEPIN_WAYLAND class UT_KeyboardPlantformWayland : public testing::Test { protected: void SetUp() override; void TearDown() override; - KeyboardPlantformWayland *m_keyboard; + KeyboardPlatformWayland *m_keyboard; }; void UT_KeyboardPlantformWayland::SetUp() { - m_keyboard = new KeyboardPlantformWayland; + m_keyboard = new KeyboardPlatformWayland; } void UT_KeyboardPlantformWayland::TearDown() @@ -23,7 +28,8 @@ void UT_KeyboardPlantformWayland::TearDown() TEST_F(UT_KeyboardPlantformWayland, basic) { - m_keyboard->isCapslockOn(); - m_keyboard->isNumlockOn(); - m_keyboard->setNumlockStatus(false); + m_keyboard->isCapsLockOn(); + m_keyboard->isNumLockOn(); + m_keyboard->setNumLockStatus(false); } +#endif diff --git a/tests/dde-lock/ut_lockcontent.cpp b/tests/dde-lock/ut_lockcontent.cpp index f68058ba..63693ebc 100644 --- a/tests/dde-lock/ut_lockcontent.cpp +++ b/tests/dde-lock/ut_lockcontent.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "lockcontent.h" #include "sessionbasemodel.h" @@ -20,13 +24,12 @@ void UT_LockContent::SetUp() m_model = new SessionBaseModel(); std::shared_ptr user_ptr(new User); m_model->updateCurrentUser(user_ptr); - - m_content = new LockContent(m_model); + LockContent::instance()->init(m_model); + m_content = LockContent::instance(); } void UT_LockContent::TearDown() { - delete m_content; delete m_model; } @@ -55,10 +58,9 @@ TEST_F(UT_LockContent, ModeTest) m_content->onStatusChanged(SessionBaseModel::PowerMode); m_content->onStatusChanged(SessionBaseModel::ShutDownMode); m_content->restoreMode(); - m_content->updateTimeFormat(true); m_content->toggleVirtualKB(); m_content->tryGrabKeyboard(); - m_content->hideToplevelWindow(); + m_model->setVisible(false); m_content->currentWorkspaceChanged(); m_content->updateWallpaper("/usr/share/wallpapers/deepin"); QTest::mouseRelease(m_content, Qt::LeftButton, Qt::KeyboardModifier::NoModifier, QPoint(0, 0)); diff --git a/tests/dde-lock/ut_lockframe.cpp b/tests/dde-lock/ut_lockframe.cpp index 7369f615..aa2dbf0d 100644 --- a/tests/dde-lock/ut_lockframe.cpp +++ b/tests/dde-lock/ut_lockframe.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "lockframe.h" #include "sessionbasemodel.h" @@ -32,11 +36,6 @@ void UT_LockFrame::TearDown() TEST_F(UT_LockFrame, frame) { - m_lockFrame->showUserList(); - m_lockFrame->showLockScreen(); - m_lockFrame->showShutdown(); - m_lockFrame->cancelShutdownInhibit(); - m_lockFrame->shutdownInhibit(SessionBaseModel::PowerAction::RequireNormal, false); m_lockFrame->handlePoweroffKey(); } diff --git a/tests/dde-lock/ut_lockworker.cpp b/tests/dde-lock/ut_lockworker.cpp index 6ca4215a..979759a3 100644 --- a/tests/dde-lock/ut_lockworker.cpp +++ b/tests/dde-lock/ut_lockworker.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "deepinauthframework.h" #include "lockworker.h" @@ -38,10 +42,10 @@ TEST_F(UT_LockWorker, worker) TEST_F(UT_LockWorker, auth) { m_worker->createAuthentication("uos"); - m_worker->startAuthentication("uos", 0); - m_worker->sendTokenToAuth("uos", 0, "123"); - m_worker->endAuthentication("uos", 0); - m_worker->destoryAuthentication("uos"); + m_worker->startAuthentication("uos", AT_None); + m_worker->sendTokenToAuth("uos", AuthCommon::AT_None, "123"); + m_worker->endAuthentication("uos", AT_None); + m_worker->destroyAuthentication("uos"); m_worker->switchToUser(m_model->currentUser()); m_worker->setLocked(false); m_worker->restartResetSessionTimer(); diff --git a/tests/dde-lock/ut_logowidget.cpp b/tests/dde-lock/ut_logowidget.cpp index 9011ec6c..c3dc680d 100644 --- a/tests/dde-lock/ut_logowidget.cpp +++ b/tests/dde-lock/ut_logowidget.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "logowidget.h" #include diff --git a/tests/dde-lock/ut_multiscreenmanager.cpp b/tests/dde-lock/ut_multiscreenmanager.cpp index 6082f073..b2edb584 100644 --- a/tests/dde-lock/ut_multiscreenmanager.cpp +++ b/tests/dde-lock/ut_multiscreenmanager.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "multiscreenmanager.h" #include @@ -26,6 +30,6 @@ void UT_MultiScreenManager::TearDown() TEST_F(UT_MultiScreenManager, basic) { m_manager->startRaiseContentFrame(); - m_manager->register_for_mutil_screen(nullptr); + m_manager->register_for_multi_screen(nullptr); m_manager->onScreenRemoved(QGuiApplication::primaryScreen()); } diff --git a/tests/dde-lock/ut_multiuserswarningview.cpp b/tests/dde-lock/ut_multiuserswarningview.cpp index 040b6cee..a133cd5b 100644 --- a/tests/dde-lock/ut_multiuserswarningview.cpp +++ b/tests/dde-lock/ut_multiuserswarningview.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "multiuserswarningview.h" #include @@ -36,10 +40,7 @@ TEST_F(UT_MultiUsersWarningView, BasicTest) { std::shared_ptr user_ptr(new User()); m_multiUsersWarningView->action(); - m_multiUsersWarningView->toggleButtonState(); - m_multiUsersWarningView->buttonClickHandle(); m_multiUsersWarningView->setAcceptReason("test"); - m_multiUsersWarningView->getUserIcon(user_ptr->avatar()); QTest::keyPress(m_multiUsersWarningView, Qt::Key_Up, Qt::KeyboardModifier::NoModifier); } diff --git a/tests/dde-lock/ut_propertygroup.cpp b/tests/dde-lock/ut_propertygroup.cpp index 6d491a30..453b193c 100644 --- a/tests/dde-lock/ut_propertygroup.cpp +++ b/tests/dde-lock/ut_propertygroup.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "propertygroup.h" #include diff --git a/tests/dde-lock/ut_sessionbasemodel.cpp b/tests/dde-lock/ut_sessionbasemodel.cpp index 2239c5bc..ec9dfd3d 100644 --- a/tests/dde-lock/ut_sessionbasemodel.cpp +++ b/tests/dde-lock/ut_sessionbasemodel.cpp @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "sessionbasemodel.h" #include "userinfo.h" +#include "dbusconstant.h" #include @@ -26,7 +31,7 @@ void UT_SessionBaseModel::TearDown() TEST_F(UT_SessionBaseModel, init) { - std::shared_ptr nativeUser(new NativeUser("/com/deepin/daemon/Accounts/User"+QString::number((getuid())))); + std::shared_ptr nativeUser(new NativeUser(QString(DSS_DBUS::accountsUserPath).arg(QString::number(getuid())))); ASSERT_TRUE(m_sessionBaseModel); m_sessionBaseModel->updateCurrentUser(nativeUser); EXPECT_EQ(m_sessionBaseModel->currentUser(), nativeUser); diff --git a/tests/dde-lock/ut_shutdownwidget.cpp b/tests/dde-lock/ut_shutdownwidget.cpp index da19f3e3..f284891f 100644 --- a/tests/dde-lock/ut_shutdownwidget.cpp +++ b/tests/dde-lock/ut_shutdownwidget.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "rounditembutton.h" #include "shutdownwidget.h" diff --git a/tests/dde-lock/ut_systemmonitor.cpp b/tests/dde-lock/ut_systemmonitor.cpp index 8a98c331..1398b5e2 100644 --- a/tests/dde-lock/ut_systemmonitor.cpp +++ b/tests/dde-lock/ut_systemmonitor.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "systemmonitor.h" #include diff --git a/tests/dde-lock/ut_timewidget.cpp b/tests/dde-lock/ut_timewidget.cpp index 562fe1bd..f773f5f0 100644 --- a/tests/dde-lock/ut_timewidget.cpp +++ b/tests/dde-lock/ut_timewidget.cpp @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "timewidget.h" #include "userinfo.h" +#include "dbusconstant.h" #include @@ -24,7 +29,7 @@ void UT_TimeWidget::TearDown() TEST_F(UT_TimeWidget, init) { - std::shared_ptr nativeUser(new NativeUser("/com/deepin/daemon/Accounts/User"+QString::number((getuid())))); + std::shared_ptr nativeUser(new NativeUser(QString(DSS_DBUS::accountsUserPath).arg(QString::number(getuid())))); bool format = nativeUser->isUse24HourFormat(); // nativeUser->userInter()->Use24HourFormatChanged(!format); timeWidget->set24HourFormat(!format); diff --git a/tests/dde-lock/ut_useravatar.cpp b/tests/dde-lock/ut_useravatar.cpp index 4f301353..6bf3488a 100644 --- a/tests/dde-lock/ut_useravatar.cpp +++ b/tests/dde-lock/ut_useravatar.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "useravatar.h" #include diff --git a/tests/dde-lock/ut_userbutton.cpp b/tests/dde-lock/ut_userbutton.cpp index e907712a..74590ff9 100644 --- a/tests/dde-lock/ut_userbutton.cpp +++ b/tests/dde-lock/ut_userbutton.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "userbutton.h" #include "userinfo.h" diff --git a/tests/dde-lock/ut_xkbparser.cpp b/tests/dde-lock/ut_xkbparser.cpp index dd682310..204cde0b 100644 --- a/tests/dde-lock/ut_xkbparser.cpp +++ b/tests/dde-lock/ut_xkbparser.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "xkbparser.h" #include diff --git a/tests/lightdm-deepin-greeter/CMakeLists.txt b/tests/lightdm-deepin-greeter/CMakeLists.txt index 32a4031f..e5c2dd3b 100644 --- a/tests/lightdm-deepin-greeter/CMakeLists.txt +++ b/tests/lightdm-deepin-greeter/CMakeLists.txt @@ -4,20 +4,23 @@ aux_source_directory(. GREETER_TEST) set(GREETER_TEST_SRCS ${GREETER_TEST} - ${authority_DBUS_SCRS} - ${transaction_DBUS_SCRS} + ${AUTH_DBUS_SCRS} ${GLOBAL_UTILS} ${GLOBAL_UTILS_DBUS} ${GLOBAL_UTILS_KEYBOARDMONITOR} ${WIDGETS} ${SESSION_WIDGETS} - ${haweiswitchos_DBUS_SCRS} + ${SWITCHOS_DBUS_SCRS} ${AUTHENTICATE} + ${DBUS_DATA_TYPES} + ${PLUGIN_MANAGER} + ${UPDATE} ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter/loginwindow.cpp ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter/greeterworker.cpp ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter/logincontent.cpp ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter/logintipswindow.cpp ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter/sessionwidget.cpp + ${PROJECT_SOURCE_DIR}/src/global_util/signal_bridge.h ) add_executable(${BIN_NAME} @@ -31,14 +34,18 @@ target_include_directories(${BIN_NAME} PUBLIC ${DTKWIDGET_INCLUDE_DIR} ${DTKCORE_INCLUDE_DIR} ${XCB_EWMH_INCLUDE_DIRS} - ${DFrameworkDBus_INCLUDE_DIRS} - ${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} - ${QGSettings_INCLUDE_DIRS} - ${Qt5X11Extras_INCLUDE_DIRS} ${Greeter_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src/lightdm-deepin-greeter ) +if (DISABLE_DSS_SNIPE) + target_include_directories(${BIN_NAME} PUBLIC + ${DFrameworkDBus_INCLUDE_DIRS} + ${Qt5Gui_PRIVATE_INCLUDE_DIRS} + ${QGSettings_INCLUDE_DIRS} + ${Qt5X11Extras_INCLUDE_DIRS} + ) +endif () target_compile_definitions(lightdm-deepin-greeter PRIVATE ENABLE_SESSION @@ -48,18 +55,21 @@ target_link_libraries(${BIN_NAME} PRIVATE ${Qt_LIBS} ${PAM_LIBRARIES} ${XCB_EWMH_LIBRARIES} - ${DFrameworkDBus_LIBRARIES} - ${DtkWidget_LIBRARIES} - ${DtkCore_LIBRARIES} - ${Qt5Widgets_LIBRARIES} - ${Qt5Concurrent_LIBRARIES} - ${Qt5X11Extras_LIBRARIES} - ${Qt5DBus_LIBRARIES} - ${Qt5Network_LIBRARIES} - ${QGSettings_LIBRARIES} + Dtk${DTK_VERSION_MAJOR}::Widget + Dtk${DTK_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Test ${Greeter_LIBRARIES} - ${Qt5Test_LIBRARIES} ${GTEST_LIBRARIES} -lpthread -lm + -lcrypto ) +if (DISABLE_DSS_SNIPE) + target_link_libraries(${BIN_NAME} PRIVATE + ${DFrameworkDBus_LIBRARIES} + ${Qt5Gui_PRIVATE_LIBRARIES} + ${QGSettings_LIBRARIES} + ${Qt5X11Extras_LIBRARIES} + KF5::WaylandClient + ) +endif () diff --git a/tests/lightdm-deepin-greeter/main.cpp b/tests/lightdm-deepin-greeter/main.cpp index 2549f98d..b867f2bd 100644 --- a/tests/lightdm-deepin-greeter/main.cpp +++ b/tests/lightdm-deepin-greeter/main.cpp @@ -1,23 +1,6 @@ -/* - * Copyright (C) 2018 ~ 2028 Uniontech Technology Co., Ltd. - * - * Author: zorowk - * - * Maintainer: zorowk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later #include #include diff --git a/tests/lightdm-deepin-greeter/ut_greeterworker.cpp b/tests/lightdm-deepin-greeter/ut_greeterworker.cpp index 93013237..920dd1ad 100644 --- a/tests/lightdm-deepin-greeter/ut_greeterworker.cpp +++ b/tests/lightdm-deepin-greeter/ut_greeterworker.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "greeterworker.h" #include "sessionbasemodel.h" @@ -34,7 +38,7 @@ TEST_F(UT_GreeterWorker, BasicTest) TEST_F(UT_GreeterWorker, AuthTest) { const QString UserName("uos"); - m_worker->checkAccount(UserName); + m_worker->checkAccount(UserName, true); // m_worker->createAuthentication(UserName); // m_worker->startAuthentication(UserName, 19); // m_worker->sendTokenToAuth(UserName, 1, "123"); @@ -47,6 +51,6 @@ TEST_F(UT_GreeterWorker, AuthTest) m_worker->showPrompt("", QLightDM::Greeter::PromptType::PromptTypeQuestion); m_worker->showMessage("", QLightDM::Greeter::MessageType::MessageTypeInfo); m_worker->authenticationComplete(); - m_worker->saveNumlockState(user_ptr, false); + m_worker->saveNumLockState(user_ptr, false); m_worker->recoveryUserKBState(user_ptr); } diff --git a/tests/lightdm-deepin-greeter/ut_logincontent.cpp b/tests/lightdm-deepin-greeter/ut_logincontent.cpp index 8a526dcc..45262e88 100644 --- a/tests/lightdm-deepin-greeter/ut_logincontent.cpp +++ b/tests/lightdm-deepin-greeter/ut_logincontent.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "logincontent.h" #include "sessionbasemodel.h" @@ -18,31 +22,30 @@ void UT_LoginContent::SetUp() m_model = new SessionBaseModel(); std::shared_ptr user_ptr(new User); m_model->updateCurrentUser(user_ptr); - - m_content = new LoginContent(m_model); + LoginContent::instance()->init(m_model); } void UT_LoginContent::TearDown() { - delete m_content; + } TEST_F(UT_LoginContent, BasicTest) { - m_content->onCurrentUserChanged(m_model->currentUser()); - m_content->pushSessionFrame(); - m_content->pushTipsFrame(); - m_content->popTipsFrame(); + LoginContent::instance()->onCurrentUserChanged(m_model->currentUser()); + LoginContent::instance()->pushSessionFrame(); + LoginContent::instance()->pushTipsFrame(); + LoginContent::instance()->popTipsFrame(); } TEST_F(UT_LoginContent, ModeTest) { - m_content->onStatusChanged(SessionBaseModel::NoStatus); - m_content->onStatusChanged(SessionBaseModel::PowerMode); - m_content->onStatusChanged(SessionBaseModel::ConfirmPasswordMode); - m_content->onStatusChanged(SessionBaseModel::UserMode); - m_content->onStatusChanged(SessionBaseModel::SessionMode); - m_content->onStatusChanged(SessionBaseModel::PowerMode); - m_content->onStatusChanged(SessionBaseModel::ShutDownMode); - m_content->restoreMode(); + LoginContent::instance()->onStatusChanged(SessionBaseModel::NoStatus); + LoginContent::instance()->onStatusChanged(SessionBaseModel::PowerMode); + LoginContent::instance()->onStatusChanged(SessionBaseModel::ConfirmPasswordMode); + LoginContent::instance()->onStatusChanged(SessionBaseModel::UserMode); + LoginContent::instance()->onStatusChanged(SessionBaseModel::SessionMode); + LoginContent::instance()->onStatusChanged(SessionBaseModel::PowerMode); + LoginContent::instance()->onStatusChanged(SessionBaseModel::ShutDownMode); + LoginContent::instance()->restoreMode(); } diff --git a/tests/lightdm-deepin-greeter/ut_logintipswindow.cpp b/tests/lightdm-deepin-greeter/ut_logintipswindow.cpp index a7992ac2..810c3495 100644 --- a/tests/lightdm-deepin-greeter/ut_logintipswindow.cpp +++ b/tests/lightdm-deepin-greeter/ut_logintipswindow.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "logintipswindow.h" #include diff --git a/tests/lightdm-deepin-greeter/ut_loginwindow.cpp b/tests/lightdm-deepin-greeter/ut_loginwindow.cpp index 81ec9ae3..59277b6c 100644 --- a/tests/lightdm-deepin-greeter/ut_loginwindow.cpp +++ b/tests/lightdm-deepin-greeter/ut_loginwindow.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "loginwindow.h" #include "sessionbasemodel.h" #include "userinfo.h" diff --git a/tests/lightdm-deepin-greeter/ut_sessionwidget.cpp b/tests/lightdm-deepin-greeter/ut_sessionwidget.cpp index 4b5a57ea..6c1f60e2 100644 --- a/tests/lightdm-deepin-greeter/ut_sessionwidget.cpp +++ b/tests/lightdm-deepin-greeter/ut_sessionwidget.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + #include "sessionwidget.h" #include diff --git a/tests/test_gm.cc b/tests/test_gm.cc new file mode 100644 index 00000000..f84fd2ad --- /dev/null +++ b/tests/test_gm.cc @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#ifdef __cplusplus +} +#endif + + +int main(int argc, char *argv[]) +{ + const unsigned char ct[] = {}; + size_t ct_size; + size_t *pt_size; + sm2_plaintext_size(ct, ct_size, pt_size); + return 0; +} diff --git a/tests/wayland_test.cc b/tests/wayland_test.cc new file mode 100644 index 00000000..856a5d8f --- /dev/null +++ b/tests/wayland_test.cc @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include + +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/toolGenerate/dconfig2cpp/lightdm-deepin-greeter-default-wayland.hpp b/toolGenerate/dconfig2cpp/lightdm-deepin-greeter-default-wayland.hpp new file mode 100644 index 00000000..3659f0c5 --- /dev/null +++ b/toolGenerate/dconfig2cpp/lightdm-deepin-greeter-default-wayland.hpp @@ -0,0 +1,316 @@ +/** + * This file is generated by dconfig2cpp. + * Command line arguments: ./dconfig2cpp -p ./dde-session-shell/toolGenerate/dconfig2cpp ./dde-session-shell/files/wayland/lightdm-deepin-greeter-default-wayland.json + * Generation time: 2025-01-14T10:55:00 + * JSON file version: 1.0 + * + * WARNING: DO NOT MODIFY THIS FILE MANUALLY. + * If you need to change the content, please modify the dconfig2cpp tool. + */ + +#ifndef LIGHTDM-DEEPIN-GREETER-DEFAULT-WAYLAND_H +#define LIGHTDM-DEEPIN-GREETER-DEFAULT-WAYLAND_H + +#include +#include +#include +#include +#include +#include + +class lightdm-deepin-greeter-default-wayland : public QObject { + Q_OBJECT + + Q_PROPERTY(bool allowSwitchingToWayland READ allowSwitchingToWayland WRITE setAllowSwitchingToWayland NOTIFY allowSwitchingToWaylandChanged) + Q_PROPERTY(QString defaultSession READ defaultSession WRITE setDefaultSession NOTIFY defaultSessionChanged) + Q_PROPERTY(bool hideOnboard READ hideOnboard WRITE setHideOnboard NOTIFY hideOnboardChanged) + Q_PROPERTY(QList numLockState READ numLockState WRITE setNumLockState NOTIFY numLockStateChanged) + Q_PROPERTY(bool useSolidBackground READ useSolidBackground WRITE setUseSolidBackground NOTIFY useSolidBackgroundChanged) +public: + explicit lightdm-deepin-greeter-default-wayland(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit lightdm-deepin-greeter-default-wayland(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit lightdm-deepin-greeter-default-wayland(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit lightdm-deepin-greeter-default-wayland(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + ~lightdm-deepin-greeter-default-wayland() { + if (m_config.loadRelaxed()) { + m_config.loadRelaxed()->deleteLater(); + } + } + + bool allowSwitchingToWayland() const { + return p_allowSwitchingToWayland; + } + void setAllowSwitchingToWayland(const bool &value) { + auto oldValue = p_allowSwitchingToWayland; + p_allowSwitchingToWayland = value; + markPropertySet(0); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("allowSwitchingToWayland"), value); + }); + } + if (p_allowSwitchingToWayland != oldValue) { + Q_EMIT allowSwitchingToWaylandChanged(); + } + } + QString defaultSession() const { + return p_defaultSession; + } + void setDefaultSession(const QString &value) { + auto oldValue = p_defaultSession; + p_defaultSession = value; + markPropertySet(1); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("defaultSession"), value); + }); + } + if (p_defaultSession != oldValue) { + Q_EMIT defaultSessionChanged(); + } + } + bool hideOnboard() const { + return p_hideOnboard; + } + void setHideOnboard(const bool &value) { + auto oldValue = p_hideOnboard; + p_hideOnboard = value; + markPropertySet(2); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("hideOnboard"), value); + }); + } + if (p_hideOnboard != oldValue) { + Q_EMIT hideOnboardChanged(); + } + } + QList numLockState() const { + return p_numLockState; + } + void setNumLockState(const QList &value) { + auto oldValue = p_numLockState; + p_numLockState = value; + markPropertySet(3); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("numLockState"), value); + }); + } + if (p_numLockState != oldValue) { + Q_EMIT numLockStateChanged(); + } + } + bool useSolidBackground() const { + return p_useSolidBackground; + } + void setUseSolidBackground(const bool &value) { + auto oldValue = p_useSolidBackground; + p_useSolidBackground = value; + markPropertySet(4); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("useSolidBackground"), value); + }); + } + if (p_useSolidBackground != oldValue) { + Q_EMIT useSolidBackgroundChanged(); + } + } +Q_SIGNALS: + void allowSwitchingToWaylandChanged(); + void defaultSessionChanged(); + void hideOnboardChanged(); + void numLockStateChanged(); + void useSolidBackgroundChanged(); +private: + void initialize(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("allowSwitchingToWayland"), QVariant::fromValue(p_allowSwitchingToWayland)); + } else { + updateValue(QStringLiteral("allowSwitchingToWayland"), QVariant::fromValue(p_allowSwitchingToWayland)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("defaultSession"), QVariant::fromValue(p_defaultSession)); + } else { + updateValue(QStringLiteral("defaultSession"), QVariant::fromValue(p_defaultSession)); + } + if (testPropertySet(2)) { + config->setValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } else { + updateValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } + if (testPropertySet(3)) { + config->setValue(QStringLiteral("numLockState"), QVariant::fromValue(p_numLockState)); + } else { + updateValue(QStringLiteral("numLockState"), QVariant::fromValue(p_numLockState)); + } + if (testPropertySet(4)) { + config->setValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } else { + updateValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } + + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); + } + void updateValue(const QString &key, const QVariant &fallback = QVariant()) { + Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); + const QVariant &value = m_config.loadRelaxed()->value(key, fallback); + if (key == QStringLiteral("allowSwitchingToWayland")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_allowSwitchingToWayland != newValue) { + p_allowSwitchingToWayland = newValue; + Q_EMIT allowSwitchingToWaylandChanged(); + } + }); + return; + } + if (key == QStringLiteral("defaultSession")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_defaultSession != newValue) { + p_defaultSession = newValue; + Q_EMIT defaultSessionChanged(); + } + }); + return; + } + if (key == QStringLiteral("hideOnboard")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_hideOnboard != newValue) { + p_hideOnboard = newValue; + Q_EMIT hideOnboardChanged(); + } + }); + return; + } + if (key == QStringLiteral("numLockState")) { + auto newValue = qvariant_cast>(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_numLockState != newValue) { + p_numLockState = newValue; + Q_EMIT numLockStateChanged(); + } + }); + return; + } + if (key == QStringLiteral("useSolidBackground")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_useSolidBackground != newValue) { + p_useSolidBackground = newValue; + Q_EMIT useSolidBackgroundChanged(); + } + }); + return; + } + } + inline void markPropertySet(const int index) { + if (index < 32) { + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + return; + } + Q_UNREACHABLE(); + } + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); + } + QAtomicPointer m_config = nullptr; + bool p_allowSwitchingToWayland { false }; + QString p_defaultSession { QStringLiteral("Wayland") }; + bool p_hideOnboard { false }; + QList p_numLockState { QList{} }; + bool p_useSolidBackground { false }; + QAtomicInteger m_propertySetStatus0 = 0; +}; + +#endif // LIGHTDM-DEEPIN-GREETER-DEFAULT-WAYLAND_H diff --git a/toolGenerate/dconfig2cpp/org_deepin_dde_lightdm-deepin-greeter.hpp b/toolGenerate/dconfig2cpp/org_deepin_dde_lightdm-deepin-greeter.hpp new file mode 100644 index 00000000..8c6ae98b --- /dev/null +++ b/toolGenerate/dconfig2cpp/org_deepin_dde_lightdm-deepin-greeter.hpp @@ -0,0 +1,316 @@ +/** + * This file is generated by dconfig2cpp. + * Command line arguments: ./dconfig2cpp -p ./dde-session-shell/toolGenerate/dconfig2cpp ./dde-session-shell/configs/org.deepin.dde.lightdm-deepin-greeter.json + * Generation time: 2025-01-14T10:55:00 + * JSON file version: 1.0 + * + * WARNING: DO NOT MODIFY THIS FILE MANUALLY. + * If you need to change the content, please modify the dconfig2cpp tool. + */ + +#ifndef ORG_DEEPIN_DDE_LIGHTDM-DEEPIN-GREETER_H +#define ORG_DEEPIN_DDE_LIGHTDM-DEEPIN-GREETER_H + +#include +#include +#include +#include +#include +#include + +class org_deepin_dde_lightdm-deepin-greeter : public QObject { + Q_OBJECT + + Q_PROPERTY(bool allowSwitchingToWayland READ allowSwitchingToWayland WRITE setAllowSwitchingToWayland NOTIFY allowSwitchingToWaylandChanged) + Q_PROPERTY(QString defaultSession READ defaultSession WRITE setDefaultSession NOTIFY defaultSessionChanged) + Q_PROPERTY(bool hideOnboard READ hideOnboard WRITE setHideOnboard NOTIFY hideOnboardChanged) + Q_PROPERTY(QList numLockState READ numLockState WRITE setNumLockState NOTIFY numLockStateChanged) + Q_PROPERTY(bool useSolidBackground READ useSolidBackground WRITE setUseSolidBackground NOTIFY useSolidBackgroundChanged) +public: + explicit org_deepin_dde_lightdm-deepin-greeter(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lightdm-deepin-greeter(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lightdm-deepin-greeter(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lightdm-deepin-greeter(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + ~org_deepin_dde_lightdm-deepin-greeter() { + if (m_config.loadRelaxed()) { + m_config.loadRelaxed()->deleteLater(); + } + } + + bool allowSwitchingToWayland() const { + return p_allowSwitchingToWayland; + } + void setAllowSwitchingToWayland(const bool &value) { + auto oldValue = p_allowSwitchingToWayland; + p_allowSwitchingToWayland = value; + markPropertySet(0); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("allowSwitchingToWayland"), value); + }); + } + if (p_allowSwitchingToWayland != oldValue) { + Q_EMIT allowSwitchingToWaylandChanged(); + } + } + QString defaultSession() const { + return p_defaultSession; + } + void setDefaultSession(const QString &value) { + auto oldValue = p_defaultSession; + p_defaultSession = value; + markPropertySet(1); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("defaultSession"), value); + }); + } + if (p_defaultSession != oldValue) { + Q_EMIT defaultSessionChanged(); + } + } + bool hideOnboard() const { + return p_hideOnboard; + } + void setHideOnboard(const bool &value) { + auto oldValue = p_hideOnboard; + p_hideOnboard = value; + markPropertySet(2); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("hideOnboard"), value); + }); + } + if (p_hideOnboard != oldValue) { + Q_EMIT hideOnboardChanged(); + } + } + QList numLockState() const { + return p_numLockState; + } + void setNumLockState(const QList &value) { + auto oldValue = p_numLockState; + p_numLockState = value; + markPropertySet(3); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("numLockState"), value); + }); + } + if (p_numLockState != oldValue) { + Q_EMIT numLockStateChanged(); + } + } + bool useSolidBackground() const { + return p_useSolidBackground; + } + void setUseSolidBackground(const bool &value) { + auto oldValue = p_useSolidBackground; + p_useSolidBackground = value; + markPropertySet(4); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("useSolidBackground"), value); + }); + } + if (p_useSolidBackground != oldValue) { + Q_EMIT useSolidBackgroundChanged(); + } + } +Q_SIGNALS: + void allowSwitchingToWaylandChanged(); + void defaultSessionChanged(); + void hideOnboardChanged(); + void numLockStateChanged(); + void useSolidBackgroundChanged(); +private: + void initialize(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("allowSwitchingToWayland"), QVariant::fromValue(p_allowSwitchingToWayland)); + } else { + updateValue(QStringLiteral("allowSwitchingToWayland"), QVariant::fromValue(p_allowSwitchingToWayland)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("defaultSession"), QVariant::fromValue(p_defaultSession)); + } else { + updateValue(QStringLiteral("defaultSession"), QVariant::fromValue(p_defaultSession)); + } + if (testPropertySet(2)) { + config->setValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } else { + updateValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } + if (testPropertySet(3)) { + config->setValue(QStringLiteral("numLockState"), QVariant::fromValue(p_numLockState)); + } else { + updateValue(QStringLiteral("numLockState"), QVariant::fromValue(p_numLockState)); + } + if (testPropertySet(4)) { + config->setValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } else { + updateValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } + + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); + } + void updateValue(const QString &key, const QVariant &fallback = QVariant()) { + Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); + const QVariant &value = m_config.loadRelaxed()->value(key, fallback); + if (key == QStringLiteral("allowSwitchingToWayland")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_allowSwitchingToWayland != newValue) { + p_allowSwitchingToWayland = newValue; + Q_EMIT allowSwitchingToWaylandChanged(); + } + }); + return; + } + if (key == QStringLiteral("defaultSession")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_defaultSession != newValue) { + p_defaultSession = newValue; + Q_EMIT defaultSessionChanged(); + } + }); + return; + } + if (key == QStringLiteral("hideOnboard")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_hideOnboard != newValue) { + p_hideOnboard = newValue; + Q_EMIT hideOnboardChanged(); + } + }); + return; + } + if (key == QStringLiteral("numLockState")) { + auto newValue = qvariant_cast>(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_numLockState != newValue) { + p_numLockState = newValue; + Q_EMIT numLockStateChanged(); + } + }); + return; + } + if (key == QStringLiteral("useSolidBackground")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_useSolidBackground != newValue) { + p_useSolidBackground = newValue; + Q_EMIT useSolidBackgroundChanged(); + } + }); + return; + } + } + inline void markPropertySet(const int index) { + if (index < 32) { + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + return; + } + Q_UNREACHABLE(); + } + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); + } + QAtomicPointer m_config = nullptr; + bool p_allowSwitchingToWayland { true }; + QString p_defaultSession { QStringLiteral("deepin") }; + bool p_hideOnboard { false }; + QList p_numLockState { QList{} }; + bool p_useSolidBackground { false }; + QAtomicInteger m_propertySetStatus0 = 0; +}; + +#endif // ORG_DEEPIN_DDE_LIGHTDM-DEEPIN-GREETER_H diff --git a/toolGenerate/dconfig2cpp/org_deepin_dde_lock.hpp b/toolGenerate/dconfig2cpp/org_deepin_dde_lock.hpp new file mode 100644 index 00000000..14dcdff4 --- /dev/null +++ b/toolGenerate/dconfig2cpp/org_deepin_dde_lock.hpp @@ -0,0 +1,282 @@ +/** + * This file is generated by dconfig2cpp. + * Command line arguments: ./dconfig2cpp -p ./dde-session-shell/toolGenerate/dconfig2cpp ./dde-session-shell/configs/org.deepin.dde.lock.json + * Generation time: 2025-01-14T10:55:00 + * JSON file version: 1.0 + * + * WARNING: DO NOT MODIFY THIS FILE MANUALLY. + * If you need to change the content, please modify the dconfig2cpp tool. + */ + +#ifndef ORG_DEEPIN_DDE_LOCK_H +#define ORG_DEEPIN_DDE_LOCK_H + +#include +#include +#include +#include +#include +#include + +class org_deepin_dde_lock : public QObject { + Q_OBJECT + + Q_PROPERTY(bool autoExit READ autoExit WRITE setAutoExit NOTIFY autoExitChanged) + Q_PROPERTY(bool hideLogoutButton READ hideLogoutButton WRITE setHideLogoutButton NOTIFY hideLogoutButtonChanged) + Q_PROPERTY(bool hideOnboard READ hideOnboard WRITE setHideOnboard NOTIFY hideOnboardChanged) + Q_PROPERTY(bool useSolidBackground READ useSolidBackground WRITE setUseSolidBackground NOTIFY useSolidBackgroundChanged) +public: + explicit org_deepin_dde_lock(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lock(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lock(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + explicit org_deepin_dde_lock(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr) + : QObject(parent) { + + if (!thread->isRunning()) { + qWarning() << QStringLiteral("Warning: The provided thread is not running."); + } + Q_ASSERT(QThread::currentThread() != thread); + auto worker = new QObject(); + worker->moveToThread(thread); + QMetaObject::invokeMethod(worker, [=]() { + auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr); + if (!config) { + qWarning() << QStringLiteral("Failed to create DConfig instance."); + worker->deleteLater(); + return; + } + config->moveToThread(QThread::currentThread()); + initialize(config); + worker->deleteLater(); + }); + } + ~org_deepin_dde_lock() { + if (m_config.loadRelaxed()) { + m_config.loadRelaxed()->deleteLater(); + } + } + + bool autoExit() const { + return p_autoExit; + } + void setAutoExit(const bool &value) { + auto oldValue = p_autoExit; + p_autoExit = value; + markPropertySet(0); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("autoExit"), value); + }); + } + if (p_autoExit != oldValue) { + Q_EMIT autoExitChanged(); + } + } + bool hideLogoutButton() const { + return p_hideLogoutButton; + } + void setHideLogoutButton(const bool &value) { + auto oldValue = p_hideLogoutButton; + p_hideLogoutButton = value; + markPropertySet(1); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("hideLogoutButton"), value); + }); + } + if (p_hideLogoutButton != oldValue) { + Q_EMIT hideLogoutButtonChanged(); + } + } + bool hideOnboard() const { + return p_hideOnboard; + } + void setHideOnboard(const bool &value) { + auto oldValue = p_hideOnboard; + p_hideOnboard = value; + markPropertySet(2); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("hideOnboard"), value); + }); + } + if (p_hideOnboard != oldValue) { + Q_EMIT hideOnboardChanged(); + } + } + bool useSolidBackground() const { + return p_useSolidBackground; + } + void setUseSolidBackground(const bool &value) { + auto oldValue = p_useSolidBackground; + p_useSolidBackground = value; + markPropertySet(3); + if (auto config = m_config.loadRelaxed()) { + QMetaObject::invokeMethod(config, [this, value]() { + m_config.loadRelaxed()->setValue(QStringLiteral("useSolidBackground"), value); + }); + } + if (p_useSolidBackground != oldValue) { + Q_EMIT useSolidBackgroundChanged(); + } + } +Q_SIGNALS: + void autoExitChanged(); + void hideLogoutButtonChanged(); + void hideOnboardChanged(); + void useSolidBackgroundChanged(); +private: + void initialize(DTK_CORE_NAMESPACE::DConfig *config) { + Q_ASSERT(!m_config.loadRelaxed()); + m_config.storeRelaxed(config); + if (testPropertySet(0)) { + config->setValue(QStringLiteral("autoExit"), QVariant::fromValue(p_autoExit)); + } else { + updateValue(QStringLiteral("autoExit"), QVariant::fromValue(p_autoExit)); + } + if (testPropertySet(1)) { + config->setValue(QStringLiteral("hideLogoutButton"), QVariant::fromValue(p_hideLogoutButton)); + } else { + updateValue(QStringLiteral("hideLogoutButton"), QVariant::fromValue(p_hideLogoutButton)); + } + if (testPropertySet(2)) { + config->setValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } else { + updateValue(QStringLiteral("hideOnboard"), QVariant::fromValue(p_hideOnboard)); + } + if (testPropertySet(3)) { + config->setValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } else { + updateValue(QStringLiteral("useSolidBackground"), QVariant::fromValue(p_useSolidBackground)); + } + + connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) { + updateValue(key); + }, Qt::DirectConnection); + } + void updateValue(const QString &key, const QVariant &fallback = QVariant()) { + Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread()); + const QVariant &value = m_config.loadRelaxed()->value(key, fallback); + if (key == QStringLiteral("autoExit")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_autoExit != newValue) { + p_autoExit = newValue; + Q_EMIT autoExitChanged(); + } + }); + return; + } + if (key == QStringLiteral("hideLogoutButton")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_hideLogoutButton != newValue) { + p_hideLogoutButton = newValue; + Q_EMIT hideLogoutButtonChanged(); + } + }); + return; + } + if (key == QStringLiteral("hideOnboard")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_hideOnboard != newValue) { + p_hideOnboard = newValue; + Q_EMIT hideOnboardChanged(); + } + }); + return; + } + if (key == QStringLiteral("useSolidBackground")) { + auto newValue = qvariant_cast(value); + QMetaObject::invokeMethod(this, [this, newValue]() { + if (p_useSolidBackground != newValue) { + p_useSolidBackground = newValue; + Q_EMIT useSolidBackgroundChanged(); + } + }); + return; + } + } + inline void markPropertySet(const int index) { + if (index < 32) { + m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0)); + return; + } + Q_UNREACHABLE(); + } + inline bool testPropertySet(const int index) const { + if (index < 32) { + return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0))); + } + Q_UNREACHABLE(); + } + QAtomicPointer m_config = nullptr; + bool p_autoExit { false }; + bool p_hideLogoutButton { false }; + bool p_hideOnboard { false }; + bool p_useSolidBackground { false }; + QAtomicInteger m_propertySetStatus0 = 0; +}; + +#endif // ORG_DEEPIN_DDE_LOCK_H diff --git a/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.cpp b/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.cpp new file mode 100644 index 00000000..cd92bede --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.cpp @@ -0,0 +1,399 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/com.deepin.wm.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wm.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class WmAdaptor + */ + +WmAdaptor::WmAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +WmAdaptor::~WmAdaptor() +{ + // destructor +} + +bool WmAdaptor::compositingAllowSwitch() const +{ + // get the value of property compositingAllowSwitch + return qvariant_cast< bool >(parent()->property("compositingAllowSwitch")); +} + +bool WmAdaptor::compositingEnabled() const +{ + // get the value of property compositingEnabled + return qvariant_cast< bool >(parent()->property("compositingEnabled")); +} + +void WmAdaptor::setCompositingEnabled(bool value) +{ + // set the value of property compositingEnabled + parent()->setProperty("compositingEnabled", QVariant::fromValue(value)); +} + +bool WmAdaptor::compositingPossible() const +{ + // get the value of property compositingPossible + return qvariant_cast< bool >(parent()->property("compositingPossible")); +} + +int WmAdaptor::cursorSize() const +{ + // get the value of property cursorSize + return qvariant_cast< int >(parent()->property("cursorSize")); +} + +void WmAdaptor::setCursorSize(int value) +{ + // set the value of property cursorSize + parent()->setProperty("cursorSize", QVariant::fromValue(value)); +} + +QString WmAdaptor::cursorTheme() const +{ + // get the value of property cursorTheme + return qvariant_cast< QString >(parent()->property("cursorTheme")); +} + +void WmAdaptor::setCursorTheme(const QString &value) +{ + // set the value of property cursorTheme + parent()->setProperty("cursorTheme", QVariant::fromValue(value)); +} + +bool WmAdaptor::zoneEnabled() const +{ + // get the value of property zoneEnabled + return qvariant_cast< bool >(parent()->property("zoneEnabled")); +} + +void WmAdaptor::setZoneEnabled(bool value) +{ + // set the value of property zoneEnabled + parent()->setProperty("zoneEnabled", QVariant::fromValue(value)); +} + +void WmAdaptor::BeginToMoveActiveWindow() +{ + // handle method call com.deepin.wm.BeginToMoveActiveWindow + QMetaObject::invokeMethod(parent(), "BeginToMoveActiveWindow"); +} + +void WmAdaptor::CancelPreviewWindow() +{ + // handle method call com.deepin.wm.CancelPreviewWindow + QMetaObject::invokeMethod(parent(), "CancelPreviewWindow"); +} + +void WmAdaptor::ChangeCurrentWorkspaceBackground(const QString &uri) +{ + // handle method call com.deepin.wm.ChangeCurrentWorkspaceBackground + QMetaObject::invokeMethod(parent(), "ChangeCurrentWorkspaceBackground", Q_ARG(QString, uri)); +} + +void WmAdaptor::ClearMoveStatus() +{ + // handle method call com.deepin.wm.ClearMoveStatus + QMetaObject::invokeMethod(parent(), "ClearMoveStatus"); +} + +void WmAdaptor::EnableZoneDetected(bool enabled) +{ + // handle method call com.deepin.wm.EnableZoneDetected + QMetaObject::invokeMethod(parent(), "EnableZoneDetected", Q_ARG(bool, enabled)); +} + +QStringList WmAdaptor::GetAccel(const QString &id) +{ + // handle method call com.deepin.wm.GetAccel + QStringList data; + QMetaObject::invokeMethod(parent(), "GetAccel", Q_RETURN_ARG(QStringList, data), Q_ARG(QString, id)); + return data; +} + +QString WmAdaptor::GetAllAccels() +{ + // handle method call com.deepin.wm.GetAllAccels + QString data; + QMetaObject::invokeMethod(parent(), "GetAllAccels", Q_RETURN_ARG(QString, data)); + return data; +} + +bool WmAdaptor::GetCurrentDesktopStatus() +{ + // handle method call com.deepin.wm.GetCurrentDesktopStatus + bool isDesktop; + QMetaObject::invokeMethod(parent(), "GetCurrentDesktopStatus", Q_RETURN_ARG(bool, isDesktop)); + return isDesktop; +} + +int WmAdaptor::GetCurrentWorkspace() +{ + // handle method call com.deepin.wm.GetCurrentWorkspace + int index; + QMetaObject::invokeMethod(parent(), "GetCurrentWorkspace", Q_RETURN_ARG(int, index)); + return index; +} + +QString WmAdaptor::GetCurrentWorkspaceBackground() +{ + // handle method call com.deepin.wm.GetCurrentWorkspaceBackground + QString result; + QMetaObject::invokeMethod(parent(), "GetCurrentWorkspaceBackground", Q_RETURN_ARG(QString, result)); + return result; +} + +QString WmAdaptor::GetCurrentWorkspaceBackgroundForMonitor(const QString &strMonitorName) +{ + // handle method call com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor + QString result; + QMetaObject::invokeMethod(parent(), "GetCurrentWorkspaceBackgroundForMonitor", Q_RETURN_ARG(QString, result), Q_ARG(QString, strMonitorName)); + return result; +} + +QStringList WmAdaptor::GetDefaultAccel(const QString &id) +{ + // handle method call com.deepin.wm.GetDefaultAccel + QStringList data; + QMetaObject::invokeMethod(parent(), "GetDefaultAccel", Q_RETURN_ARG(QStringList, data), Q_ARG(QString, id)); + return data; +} + +bool WmAdaptor::GetIsShowDesktop() +{ + // handle method call com.deepin.wm.GetIsShowDesktop + bool isShowDesktop; + QMetaObject::invokeMethod(parent(), "GetIsShowDesktop", Q_RETURN_ARG(bool, isShowDesktop)); + return isShowDesktop; +} + +bool WmAdaptor::GetMultiTaskingStatus() +{ + // handle method call com.deepin.wm.GetMultiTaskingStatus + bool isActive; + QMetaObject::invokeMethod(parent(), "GetMultiTaskingStatus", Q_RETURN_ARG(bool, isActive)); + return isActive; +} + +double WmAdaptor::GetTouchBorderInterval() +{ + // handle method call com.deepin.wm.GetTouchBorderInterval + double interval; + QMetaObject::invokeMethod(parent(), "GetTouchBorderInterval", Q_RETURN_ARG(double, interval)); + return interval; +} + +QString WmAdaptor::GetWorkspaceBackground(int index) +{ + // handle method call com.deepin.wm.GetWorkspaceBackground + QString result; + QMetaObject::invokeMethod(parent(), "GetWorkspaceBackground", Q_RETURN_ARG(QString, result), Q_ARG(int, index)); + return result; +} + +QString WmAdaptor::GetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName) +{ + // handle method call com.deepin.wm.GetWorkspaceBackgroundForMonitor + QString result; + QMetaObject::invokeMethod(parent(), "GetWorkspaceBackgroundForMonitor", Q_RETURN_ARG(QString, result), Q_ARG(int, index), Q_ARG(QString, strMonitorName)); + return result; +} + +void WmAdaptor::MinimizeActiveWindow() +{ + // handle method call com.deepin.wm.MinimizeActiveWindow + QMetaObject::invokeMethod(parent(), "MinimizeActiveWindow"); +} + +void WmAdaptor::NextWorkspace() +{ + // handle method call com.deepin.wm.NextWorkspace + QMetaObject::invokeMethod(parent(), "NextWorkspace"); +} + +void WmAdaptor::PerformAction(int type) +{ + // handle method call com.deepin.wm.PerformAction + QMetaObject::invokeMethod(parent(), "PerformAction", Q_ARG(int, type)); +} + +void WmAdaptor::PresentWindows(const QList &xids) +{ + // handle method call com.deepin.wm.PresentWindows + QMetaObject::invokeMethod(parent(), "PresentWindows", Q_ARG(QList, xids)); +} + +void WmAdaptor::PreviewWindow(uint xid) +{ + // handle method call com.deepin.wm.PreviewWindow + QMetaObject::invokeMethod(parent(), "PreviewWindow", Q_ARG(uint, xid)); +} + +void WmAdaptor::PreviousWorkspace() +{ + // handle method call com.deepin.wm.PreviousWorkspace + QMetaObject::invokeMethod(parent(), "PreviousWorkspace"); +} + +void WmAdaptor::RemoveAccel(const QString &id) +{ + // handle method call com.deepin.wm.RemoveAccel + QMetaObject::invokeMethod(parent(), "RemoveAccel", Q_ARG(QString, id)); +} + +bool WmAdaptor::SetAccel(const QString &data) +{ + // handle method call com.deepin.wm.SetAccel + bool result; + QMetaObject::invokeMethod(parent(), "SetAccel", Q_RETURN_ARG(bool, result), Q_ARG(QString, data)); + return result; +} + +void WmAdaptor::SetCurrentWorkspace(int index) +{ + // handle method call com.deepin.wm.SetCurrentWorkspace + QMetaObject::invokeMethod(parent(), "SetCurrentWorkspace", Q_ARG(int, index)); +} + +void WmAdaptor::SetCurrentWorkspaceBackground(const QString &uri) +{ + // handle method call com.deepin.wm.SetCurrentWorkspaceBackground + QMetaObject::invokeMethod(parent(), "SetCurrentWorkspaceBackground", Q_ARG(QString, uri)); +} + +void WmAdaptor::SetCurrentWorkspaceBackgroundForMonitor(const QString &uri, const QString &strMonitorName) +{ + // handle method call com.deepin.wm.SetCurrentWorkspaceBackgroundForMonitor + QMetaObject::invokeMethod(parent(), "SetCurrentWorkspaceBackgroundForMonitor", Q_ARG(QString, uri), Q_ARG(QString, strMonitorName)); +} + +void WmAdaptor::SetDecorationDeepinTheme(const QString &deepinThemeName) +{ + // handle method call com.deepin.wm.SetDecorationDeepinTheme + QMetaObject::invokeMethod(parent(), "SetDecorationDeepinTheme", Q_ARG(QString, deepinThemeName)); +} + +void WmAdaptor::SetDecorationTheme(const QString &themeType, const QString &themeName) +{ + // handle method call com.deepin.wm.SetDecorationTheme + QMetaObject::invokeMethod(parent(), "SetDecorationTheme", Q_ARG(QString, themeType), Q_ARG(QString, themeName)); +} + +void WmAdaptor::SetMultiTaskingStatus(bool isActive) +{ + // handle method call com.deepin.wm.SetMultiTaskingStatus + QMetaObject::invokeMethod(parent(), "SetMultiTaskingStatus", Q_ARG(bool, isActive)); +} + +void WmAdaptor::SetShowDesktop(bool isShowDesktop) +{ + // handle method call com.deepin.wm.SetShowDesktop + QMetaObject::invokeMethod(parent(), "SetShowDesktop", Q_ARG(bool, isShowDesktop)); +} + +void WmAdaptor::SetTouchBorderInterval(double interval) +{ + // handle method call com.deepin.wm.SetTouchBorderInterval + QMetaObject::invokeMethod(parent(), "SetTouchBorderInterval", Q_ARG(double, interval)); +} + +void WmAdaptor::SetTransientBackground(const QString &in0) +{ + // handle method call com.deepin.wm.SetTransientBackground + QMetaObject::invokeMethod(parent(), "SetTransientBackground", Q_ARG(QString, in0)); +} + +void WmAdaptor::SetTransientBackgroundForMonitor(const QString &uri, const QString &strMonitorName) +{ + // handle method call com.deepin.wm.SetTransientBackgroundForMonitor + QMetaObject::invokeMethod(parent(), "SetTransientBackgroundForMonitor", Q_ARG(QString, uri), Q_ARG(QString, strMonitorName)); +} + +void WmAdaptor::SetWorkspaceBackground(int index, const QString &uri) +{ + // handle method call com.deepin.wm.SetWorkspaceBackground + QMetaObject::invokeMethod(parent(), "SetWorkspaceBackground", Q_ARG(int, index), Q_ARG(QString, uri)); +} + +void WmAdaptor::SetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName, const QString &uri) +{ + // handle method call com.deepin.wm.SetWorkspaceBackgroundForMonitor + QMetaObject::invokeMethod(parent(), "SetWorkspaceBackgroundForMonitor", Q_ARG(int, index), Q_ARG(QString, strMonitorName), Q_ARG(QString, uri)); +} + +void WmAdaptor::ShowAllWindow() +{ + // handle method call com.deepin.wm.ShowAllWindow + QMetaObject::invokeMethod(parent(), "ShowAllWindow"); +} + +void WmAdaptor::ShowWindow() +{ + // handle method call com.deepin.wm.ShowWindow + QMetaObject::invokeMethod(parent(), "ShowWindow"); +} + +void WmAdaptor::ShowWorkspace() +{ + // handle method call com.deepin.wm.ShowWorkspace + QMetaObject::invokeMethod(parent(), "ShowWorkspace"); +} + +void WmAdaptor::SwitchApplication(bool backward) +{ + // handle method call com.deepin.wm.SwitchApplication + QMetaObject::invokeMethod(parent(), "SwitchApplication", Q_ARG(bool, backward)); +} + +void WmAdaptor::SwitchToWorkspace(bool backward) +{ + // handle method call com.deepin.wm.SwitchToWorkspace + QMetaObject::invokeMethod(parent(), "SwitchToWorkspace", Q_ARG(bool, backward)); +} + +void WmAdaptor::TileActiveWindow(uint side) +{ + // handle method call com.deepin.wm.TileActiveWindow + QMetaObject::invokeMethod(parent(), "TileActiveWindow", Q_ARG(uint, side)); +} + +void WmAdaptor::ToggleActiveWindowMaximize() +{ + // handle method call com.deepin.wm.ToggleActiveWindowMaximize + QMetaObject::invokeMethod(parent(), "ToggleActiveWindowMaximize"); +} + +void WmAdaptor::TouchToMove(int x, int y) +{ + // handle method call com.deepin.wm.TouchToMove + QMetaObject::invokeMethod(parent(), "TouchToMove", Q_ARG(int, x), Q_ARG(int, y)); +} + +int WmAdaptor::WorkspaceCount() +{ + // handle method call com.deepin.wm.WorkspaceCount + int count; + QMetaObject::invokeMethod(parent(), "WorkspaceCount", Q_RETURN_ARG(int, count)); + return count; +} + diff --git a/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.h b/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.h new file mode 100644 index 00000000..24175635 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor.h @@ -0,0 +1,282 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/com.deepin.wm.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wmAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wm.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef COM_DEEPIN_WMADAPTOR_H +#define COM_DEEPIN_WMADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/com.deepin.wm.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface com.deepin.wm + */ +class WmAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.deepin.wm") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + WmAdaptor(QObject *parent); + virtual ~WmAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool compositingAllowSwitch READ compositingAllowSwitch) + bool compositingAllowSwitch() const; + + Q_PROPERTY(bool compositingEnabled READ compositingEnabled WRITE setCompositingEnabled) + bool compositingEnabled() const; + void setCompositingEnabled(bool value); + + Q_PROPERTY(bool compositingPossible READ compositingPossible) + bool compositingPossible() const; + + Q_PROPERTY(int cursorSize READ cursorSize WRITE setCursorSize) + int cursorSize() const; + void setCursorSize(int value); + + Q_PROPERTY(QString cursorTheme READ cursorTheme WRITE setCursorTheme) + QString cursorTheme() const; + void setCursorTheme(const QString &value); + + Q_PROPERTY(bool zoneEnabled READ zoneEnabled WRITE setZoneEnabled) + bool zoneEnabled() const; + void setZoneEnabled(bool value); + +public Q_SLOTS: // METHODS + void BeginToMoveActiveWindow(); + void CancelPreviewWindow(); + void ChangeCurrentWorkspaceBackground(const QString &uri); + void ClearMoveStatus(); + void EnableZoneDetected(bool enabled); + QStringList GetAccel(const QString &id); + QString GetAllAccels(); + bool GetCurrentDesktopStatus(); + int GetCurrentWorkspace(); + QString GetCurrentWorkspaceBackground(); + QString GetCurrentWorkspaceBackgroundForMonitor(const QString &strMonitorName); + QStringList GetDefaultAccel(const QString &id); + bool GetIsShowDesktop(); + bool GetMultiTaskingStatus(); + double GetTouchBorderInterval(); + QString GetWorkspaceBackground(int index); + QString GetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName); + void MinimizeActiveWindow(); + void NextWorkspace(); + void PerformAction(int type); + void PresentWindows(const QList &xids); + void PreviewWindow(uint xid); + void PreviousWorkspace(); + void RemoveAccel(const QString &id); + bool SetAccel(const QString &data); + void SetCurrentWorkspace(int index); + void SetCurrentWorkspaceBackground(const QString &uri); + void SetCurrentWorkspaceBackgroundForMonitor(const QString &uri, const QString &strMonitorName); + void SetDecorationDeepinTheme(const QString &deepinThemeName); + void SetDecorationTheme(const QString &themeType, const QString &themeName); + void SetMultiTaskingStatus(bool isActive); + void SetShowDesktop(bool isShowDesktop); + void SetTouchBorderInterval(double interval); + void SetTransientBackground(const QString &in0); + void SetTransientBackgroundForMonitor(const QString &uri, const QString &strMonitorName); + void SetWorkspaceBackground(int index, const QString &uri); + void SetWorkspaceBackgroundForMonitor(int index, const QString &strMonitorName, const QString &uri); + void ShowAllWindow(); + void ShowWindow(); + void ShowWorkspace(); + void SwitchApplication(bool backward); + void SwitchToWorkspace(bool backward); + void TileActiveWindow(uint side); + void ToggleActiveWindowMaximize(); + void TouchToMove(int x, int y); + int WorkspaceCount(); +Q_SIGNALS: // SIGNALS + void WorkspaceBackgroundChanged(int index, const QString &newUri); + void WorkspaceBackgroundChangedForMonitor(int index, const QString &strMonitorName, const QString &uri); + void WorkspaceSwitched(int from, int to); + void compositingEnabledChanged(bool enabled); + void wmCompositingEnabledChanged(bool enabled); + void workspaceCountChanged(int count); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.cpp b/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.cpp new file mode 100644 index 00000000..98e3e3a2 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.cpp @@ -0,0 +1,59 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/com.huawei.switchos.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchos.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class SwitchosAdaptor + */ + +SwitchosAdaptor::SwitchosAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +SwitchosAdaptor::~SwitchosAdaptor() +{ + // destructor +} + +uchar SwitchosAdaptor::getOsFlag() +{ + // handle method call com.huawei.switchos.getOsFlag + uchar flag; + QMetaObject::invokeMethod(parent(), "getOsFlag", Q_RETURN_ARG(uchar, flag)); + return flag; +} + +uchar SwitchosAdaptor::isDualOsSwitchAvail() +{ + // handle method call com.huawei.switchos.isDualOsSwitchAvail + uchar isAvail; + QMetaObject::invokeMethod(parent(), "isDualOsSwitchAvail", Q_RETURN_ARG(uchar, isAvail)); + return isAvail; +} + +uint SwitchosAdaptor::setOsFlag(uchar flag) +{ + // handle method call com.huawei.switchos.setOsFlag + uint result; + QMetaObject::invokeMethod(parent(), "setOsFlag", Q_RETURN_ARG(uint, result), Q_ARG(uchar, flag)); + return result; +} + diff --git a/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.h b/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.h new file mode 100644 index 00000000..69a84c7f --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor.h @@ -0,0 +1,60 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/com.huawei.switchos.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchosAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchos.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef COM_HUAWEI_SWITCHOSADAPTOR_H +#define COM_HUAWEI_SWITCHOSADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/com.huawei.switchos.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface com.huawei.switchos + */ +class SwitchosAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.huawei.switchos") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + SwitchosAdaptor(QObject *parent); + virtual ~SwitchosAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + uchar getOsFlag(); + uchar isDualOsSwitchAvail(); + uint setOsFlag(uchar flag); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.cpp new file mode 100644 index 00000000..37c74a28 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.cpp @@ -0,0 +1,361 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Accounts1.User.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.User.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class UserAdaptor + */ + +UserAdaptor::UserAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +UserAdaptor::~UserAdaptor() +{ + // destructor +} + +int UserAdaptor::accountType() const +{ + // get the value of property AccountType + return qvariant_cast< int >(parent()->property("AccountType")); +} + +bool UserAdaptor::automaticLogin() const +{ + // get the value of property AutomaticLogin + return qvariant_cast< bool >(parent()->property("AutomaticLogin")); +} + +qulonglong UserAdaptor::createdTime() const +{ + // get the value of property CreatedTime + return qvariant_cast< qulonglong >(parent()->property("CreatedTime")); +} + +QStringList UserAdaptor::desktopBackgrounds() const +{ + // get the value of property DesktopBackgrounds + return qvariant_cast< QStringList >(parent()->property("DesktopBackgrounds")); +} + +QString UserAdaptor::fullName() const +{ + // get the value of property FullName + return qvariant_cast< QString >(parent()->property("FullName")); +} + +QString UserAdaptor::gid() const +{ + // get the value of property Gid + return qvariant_cast< QString >(parent()->property("Gid")); +} + +QString UserAdaptor::greeterBackground() const +{ + // get the value of property GreeterBackground + return qvariant_cast< QString >(parent()->property("GreeterBackground")); +} + +QStringList UserAdaptor::groups() const +{ + // get the value of property Groups + return qvariant_cast< QStringList >(parent()->property("Groups")); +} + +QStringList UserAdaptor::historyLayout() const +{ + // get the value of property HistoryLayout + return qvariant_cast< QStringList >(parent()->property("HistoryLayout")); +} + +QString UserAdaptor::homeDir() const +{ + // get the value of property HomeDir + return qvariant_cast< QString >(parent()->property("HomeDir")); +} + +QString UserAdaptor::iconFile() const +{ + // get the value of property IconFile + return qvariant_cast< QString >(parent()->property("IconFile")); +} + +QStringList UserAdaptor::iconList() const +{ + // get the value of property IconList + return qvariant_cast< QStringList >(parent()->property("IconList")); +} + +QString UserAdaptor::layout() const +{ + // get the value of property Layout + return qvariant_cast< QString >(parent()->property("Layout")); +} + +QString UserAdaptor::locale() const +{ + // get the value of property Locale + return qvariant_cast< QString >(parent()->property("Locale")); +} + +bool UserAdaptor::locked() const +{ + // get the value of property Locked + return qvariant_cast< bool >(parent()->property("Locked")); +} + +qulonglong UserAdaptor::loginTime() const +{ + // get the value of property LoginTime + return qvariant_cast< qulonglong >(parent()->property("LoginTime")); +} + +int UserAdaptor::longDateFormat() const +{ + // get the value of property LongDateFormat + return qvariant_cast< int >(parent()->property("LongDateFormat")); +} + +int UserAdaptor::longTimeFormat() const +{ + // get the value of property LongTimeFormat + return qvariant_cast< int >(parent()->property("LongTimeFormat")); +} + +int UserAdaptor::maxPasswordAge() const +{ + // get the value of property MaxPasswordAge + return qvariant_cast< int >(parent()->property("MaxPasswordAge")); +} + +bool UserAdaptor::noPasswdLogin() const +{ + // get the value of property NoPasswdLogin + return qvariant_cast< bool >(parent()->property("NoPasswdLogin")); +} + +QString UserAdaptor::passwordHint() const +{ + // get the value of property PasswordHint + return qvariant_cast< QString >(parent()->property("PasswordHint")); +} + +int UserAdaptor::passwordLastChange() const +{ + // get the value of property PasswordLastChange + return qvariant_cast< int >(parent()->property("PasswordLastChange")); +} + +QString UserAdaptor::passwordStatus() const +{ + // get the value of property PasswordStatus + return qvariant_cast< QString >(parent()->property("PasswordStatus")); +} + +QString UserAdaptor::shell() const +{ + // get the value of property Shell + return qvariant_cast< QString >(parent()->property("Shell")); +} + +int UserAdaptor::shortDateFormat() const +{ + // get the value of property ShortDateFormat + return qvariant_cast< int >(parent()->property("ShortDateFormat")); +} + +int UserAdaptor::shortTimeFormat() const +{ + // get the value of property ShortTimeFormat + return qvariant_cast< int >(parent()->property("ShortTimeFormat")); +} + +bool UserAdaptor::systemAccount() const +{ + // get the value of property SystemAccount + return qvariant_cast< bool >(parent()->property("SystemAccount")); +} + +QString UserAdaptor::uid() const +{ + // get the value of property Uid + return qvariant_cast< QString >(parent()->property("Uid")); +} + +bool UserAdaptor::use24HourFormat() const +{ + // get the value of property Use24HourFormat + return qvariant_cast< bool >(parent()->property("Use24HourFormat")); +} + +QString UserAdaptor::userName() const +{ + // get the value of property UserName + return qvariant_cast< QString >(parent()->property("UserName")); +} + +int UserAdaptor::weekBegins() const +{ + // get the value of property WeekBegins + return qvariant_cast< int >(parent()->property("WeekBegins")); +} + +int UserAdaptor::weekdayFormat() const +{ + // get the value of property WeekdayFormat + return qvariant_cast< int >(parent()->property("WeekdayFormat")); +} + +QString UserAdaptor::xSession() const +{ + // get the value of property XSession + return qvariant_cast< QString >(parent()->property("XSession")); +} + +void UserAdaptor::AddGroup(const QString &group) +{ + // handle method call org.deepin.dde.Accounts1.User.AddGroup + QMetaObject::invokeMethod(parent(), "AddGroup", Q_ARG(QString, group)); +} + +void UserAdaptor::DeleteGroup(const QString &group) +{ + // handle method call org.deepin.dde.Accounts1.User.DeleteGroup + QMetaObject::invokeMethod(parent(), "DeleteGroup", Q_ARG(QString, group)); +} + +void UserAdaptor::DeleteIconFile(const QString &iconFile) +{ + // handle method call org.deepin.dde.Accounts1.User.DeleteIconFile + QMetaObject::invokeMethod(parent(), "DeleteIconFile", Q_ARG(QString, iconFile)); +} + +void UserAdaptor::EnableNoPasswdLogin(bool enabled) +{ + // handle method call org.deepin.dde.Accounts1.User.EnableNoPasswdLogin + QMetaObject::invokeMethod(parent(), "EnableNoPasswdLogin", Q_ARG(bool, enabled)); +} + +bool UserAdaptor::IsPasswordExpired() +{ + // handle method call org.deepin.dde.Accounts1.User.IsPasswordExpired + bool out0; + QMetaObject::invokeMethod(parent(), "IsPasswordExpired", Q_RETURN_ARG(bool, out0)); + return out0; +} + +int UserAdaptor::PasswordExpiredInfo(int &dayLeft) +{ + // handle method call org.deepin.dde.Accounts1.User.PasswordExpiredInfo + //return static_cast(parent())->PasswordExpiredInfo(dayLeft); +} + +void UserAdaptor::SetAutomaticLogin(bool enabled) +{ + // handle method call org.deepin.dde.Accounts1.User.SetAutomaticLogin + QMetaObject::invokeMethod(parent(), "SetAutomaticLogin", Q_ARG(bool, enabled)); +} + +void UserAdaptor::SetDesktopBackgrounds(const QStringList &backgrounds) +{ + // handle method call org.deepin.dde.Accounts1.User.SetDesktopBackgrounds + QMetaObject::invokeMethod(parent(), "SetDesktopBackgrounds", Q_ARG(QStringList, backgrounds)); +} + +void UserAdaptor::SetFullName(const QString &name) +{ + // handle method call org.deepin.dde.Accounts1.User.SetFullName + QMetaObject::invokeMethod(parent(), "SetFullName", Q_ARG(QString, name)); +} + +void UserAdaptor::SetGreeterBackground(const QString &background) +{ + // handle method call org.deepin.dde.Accounts1.User.SetGreeterBackground + QMetaObject::invokeMethod(parent(), "SetGreeterBackground", Q_ARG(QString, background)); +} + +void UserAdaptor::SetGroups(const QStringList &groups) +{ + // handle method call org.deepin.dde.Accounts1.User.SetGroups + QMetaObject::invokeMethod(parent(), "SetGroups", Q_ARG(QStringList, groups)); +} + +void UserAdaptor::SetHistoryLayout(const QStringList &layouts) +{ + // handle method call org.deepin.dde.Accounts1.User.SetHistoryLayout + QMetaObject::invokeMethod(parent(), "SetHistoryLayout", Q_ARG(QStringList, layouts)); +} + +void UserAdaptor::SetHomeDir(const QString &home) +{ + // handle method call org.deepin.dde.Accounts1.User.SetHomeDir + QMetaObject::invokeMethod(parent(), "SetHomeDir", Q_ARG(QString, home)); +} + +void UserAdaptor::SetIconFile(const QString &iconFile) +{ + // handle method call org.deepin.dde.Accounts1.User.SetIconFile + QMetaObject::invokeMethod(parent(), "SetIconFile", Q_ARG(QString, iconFile)); +} + +void UserAdaptor::SetLayout(const QString &layout) +{ + // handle method call org.deepin.dde.Accounts1.User.SetLayout + QMetaObject::invokeMethod(parent(), "SetLayout", Q_ARG(QString, layout)); +} + +void UserAdaptor::SetLocale(const QString &locale) +{ + // handle method call org.deepin.dde.Accounts1.User.SetLocale + QMetaObject::invokeMethod(parent(), "SetLocale", Q_ARG(QString, locale)); +} + +void UserAdaptor::SetLocked(bool locked) +{ + // handle method call org.deepin.dde.Accounts1.User.SetLocked + QMetaObject::invokeMethod(parent(), "SetLocked", Q_ARG(bool, locked)); +} + +void UserAdaptor::SetMaxPasswordAge(int nDays) +{ + // handle method call org.deepin.dde.Accounts1.User.SetMaxPasswordAge + QMetaObject::invokeMethod(parent(), "SetMaxPasswordAge", Q_ARG(int, nDays)); +} + +void UserAdaptor::SetPassword(const QString &password) +{ + // handle method call org.deepin.dde.Accounts1.User.SetPassword + QMetaObject::invokeMethod(parent(), "SetPassword", Q_ARG(QString, password)); +} + +void UserAdaptor::SetPasswordHint(const QString &hint) +{ + // handle method call org.deepin.dde.Accounts1.User.SetPasswordHint + QMetaObject::invokeMethod(parent(), "SetPasswordHint", Q_ARG(QString, hint)); +} + +void UserAdaptor::SetShell(const QString &shell) +{ + // handle method call org.deepin.dde.Accounts1.User.SetShell + QMetaObject::invokeMethod(parent(), "SetShell", Q_ARG(QString, shell)); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.h new file mode 100644 index 00000000..210b9c89 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor.h @@ -0,0 +1,264 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Accounts1.User.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.UserAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.User.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_ACCOUNTS1_USERADAPTOR_H +#define ORG_DEEPIN_DDE_ACCOUNTS1_USERADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.User.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Accounts1.User + */ +class UserAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Accounts1.User") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + UserAdaptor(QObject *parent); + virtual ~UserAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(int AccountType READ accountType) + int accountType() const; + + Q_PROPERTY(bool AutomaticLogin READ automaticLogin) + bool automaticLogin() const; + + Q_PROPERTY(qulonglong CreatedTime READ createdTime) + qulonglong createdTime() const; + + Q_PROPERTY(QStringList DesktopBackgrounds READ desktopBackgrounds) + QStringList desktopBackgrounds() const; + + Q_PROPERTY(QString FullName READ fullName) + QString fullName() const; + + Q_PROPERTY(QString Gid READ gid) + QString gid() const; + + Q_PROPERTY(QString GreeterBackground READ greeterBackground) + QString greeterBackground() const; + + Q_PROPERTY(QStringList Groups READ groups) + QStringList groups() const; + + Q_PROPERTY(QStringList HistoryLayout READ historyLayout) + QStringList historyLayout() const; + + Q_PROPERTY(QString HomeDir READ homeDir) + QString homeDir() const; + + Q_PROPERTY(QString IconFile READ iconFile) + QString iconFile() const; + + Q_PROPERTY(QStringList IconList READ iconList) + QStringList iconList() const; + + Q_PROPERTY(QString Layout READ layout) + QString layout() const; + + Q_PROPERTY(QString Locale READ locale) + QString locale() const; + + Q_PROPERTY(bool Locked READ locked) + bool locked() const; + + Q_PROPERTY(qulonglong LoginTime READ loginTime) + qulonglong loginTime() const; + + Q_PROPERTY(int LongDateFormat READ longDateFormat) + int longDateFormat() const; + + Q_PROPERTY(int LongTimeFormat READ longTimeFormat) + int longTimeFormat() const; + + Q_PROPERTY(int MaxPasswordAge READ maxPasswordAge) + int maxPasswordAge() const; + + Q_PROPERTY(bool NoPasswdLogin READ noPasswdLogin) + bool noPasswdLogin() const; + + Q_PROPERTY(QString PasswordHint READ passwordHint) + QString passwordHint() const; + + Q_PROPERTY(int PasswordLastChange READ passwordLastChange) + int passwordLastChange() const; + + Q_PROPERTY(QString PasswordStatus READ passwordStatus) + QString passwordStatus() const; + + Q_PROPERTY(QString Shell READ shell) + QString shell() const; + + Q_PROPERTY(int ShortDateFormat READ shortDateFormat) + int shortDateFormat() const; + + Q_PROPERTY(int ShortTimeFormat READ shortTimeFormat) + int shortTimeFormat() const; + + Q_PROPERTY(bool SystemAccount READ systemAccount) + bool systemAccount() const; + + Q_PROPERTY(QString Uid READ uid) + QString uid() const; + + Q_PROPERTY(bool Use24HourFormat READ use24HourFormat) + bool use24HourFormat() const; + + Q_PROPERTY(QString UserName READ userName) + QString userName() const; + + Q_PROPERTY(int WeekBegins READ weekBegins) + int weekBegins() const; + + Q_PROPERTY(int WeekdayFormat READ weekdayFormat) + int weekdayFormat() const; + + Q_PROPERTY(QString XSession READ xSession) + QString xSession() const; + +public Q_SLOTS: // METHODS + void AddGroup(const QString &group); + void DeleteGroup(const QString &group); + void DeleteIconFile(const QString &iconFile); + void EnableNoPasswdLogin(bool enabled); + bool IsPasswordExpired(); + int PasswordExpiredInfo(int &dayLeft); + void SetAutomaticLogin(bool enabled); + void SetDesktopBackgrounds(const QStringList &backgrounds); + void SetFullName(const QString &name); + void SetGreeterBackground(const QString &background); + void SetGroups(const QStringList &groups); + void SetHistoryLayout(const QStringList &layouts); + void SetHomeDir(const QString &home); + void SetIconFile(const QString &iconFile); + void SetLayout(const QString &layout); + void SetLocale(const QString &locale); + void SetLocked(bool locked); + void SetMaxPasswordAge(int nDays); + void SetPassword(const QString &password); + void SetPasswordHint(const QString &hint); + void SetShell(const QString &shell); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.cpp new file mode 100644 index 00000000..d048a0e3 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.cpp @@ -0,0 +1,133 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Accounts1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class Accounts1Adaptor + */ + +Accounts1Adaptor::Accounts1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +Accounts1Adaptor::~Accounts1Adaptor() +{ + // destructor +} + +bool Accounts1Adaptor::allowGuest() const +{ + // get the value of property AllowGuest + return qvariant_cast< bool >(parent()->property("AllowGuest")); +} + +QString Accounts1Adaptor::guestIcon() const +{ + // get the value of property GuestIcon + return qvariant_cast< QString >(parent()->property("GuestIcon")); +} + +QStringList Accounts1Adaptor::userList() const +{ + // get the value of property UserList + return qvariant_cast< QStringList >(parent()->property("UserList")); +} + +void Accounts1Adaptor::AllowGuestAccount(bool in0) +{ + // handle method call org.deepin.dde.Accounts1.AllowGuestAccount + QMetaObject::invokeMethod(parent(), "AllowGuestAccount", Q_ARG(bool, in0)); +} + +QString Accounts1Adaptor::CreateGuestAccount() +{ + // handle method call org.deepin.dde.Accounts1.CreateGuestAccount + QString out0; + QMetaObject::invokeMethod(parent(), "CreateGuestAccount", Q_RETURN_ARG(QString, out0)); + return out0; +} + +QDBusObjectPath Accounts1Adaptor::CreateUser(const QString &in0, const QString &in1, int in2) +{ + // handle method call org.deepin.dde.Accounts1.CreateUser + QDBusObjectPath out0; + QMetaObject::invokeMethod(parent(), "CreateUser", Q_RETURN_ARG(QDBusObjectPath, out0), Q_ARG(QString, in0), Q_ARG(QString, in1), Q_ARG(int, in2)); + return out0; +} + +void Accounts1Adaptor::DeleteUser(const QString &in0, bool in1) +{ + // handle method call org.deepin.dde.Accounts1.DeleteUser + QMetaObject::invokeMethod(parent(), "DeleteUser", Q_ARG(QString, in0), Q_ARG(bool, in1)); +} + +QString Accounts1Adaptor::FindUserById(const QString &in0) +{ + // handle method call org.deepin.dde.Accounts1.FindUserById + QString out0; + QMetaObject::invokeMethod(parent(), "FindUserById", Q_RETURN_ARG(QString, out0), Q_ARG(QString, in0)); + return out0; +} + +QString Accounts1Adaptor::FindUserByName(const QString &in0) +{ + // handle method call org.deepin.dde.Accounts1.FindUserByName + QString out0; + QMetaObject::invokeMethod(parent(), "FindUserByName", Q_RETURN_ARG(QString, out0), Q_ARG(QString, in0)); + return out0; +} + +QStringList Accounts1Adaptor::GetGroups() +{ + // handle method call org.deepin.dde.Accounts1.GetGroups + QStringList out0; + QMetaObject::invokeMethod(parent(), "GetGroups", Q_RETURN_ARG(QStringList, out0)); + return out0; +} + +QStringList Accounts1Adaptor::GetPresetGroups(int in0) +{ + // handle method call org.deepin.dde.Accounts1.GetPresetGroups + QStringList out0; + QMetaObject::invokeMethod(parent(), "GetPresetGroups", Q_RETURN_ARG(QStringList, out0), Q_ARG(int, in0)); + return out0; +} + +bool Accounts1Adaptor::IsPasswordValid(const QString &in0, QString &out1, int &out2) +{ + // handle method call org.deepin.dde.Accounts1.IsPasswordValid + //return static_cast(parent())->IsPasswordValid(in0, out1, out2); +} + +bool Accounts1Adaptor::IsUsernameValid(const QString &in0, QString &out1, int &out2) +{ + // handle method call org.deepin.dde.Accounts1.IsUsernameValid + //return static_cast(parent())->IsUsernameValid(in0, out1, out2); +} + +QString Accounts1Adaptor::RandUserIcon() +{ + // handle method call org.deepin.dde.Accounts1.RandUserIcon + QString out0; + QMetaObject::invokeMethod(parent(), "RandUserIcon", Q_RETURN_ARG(QString, out0)); + return out0; +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.h new file mode 100644 index 00000000..72638118 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor.h @@ -0,0 +1,124 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Accounts1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_ACCOUNTS1ADAPTOR_H +#define ORG_DEEPIN_DDE_ACCOUNTS1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Accounts1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Accounts1 + */ +class Accounts1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Accounts1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + Accounts1Adaptor(QObject *parent); + virtual ~Accounts1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool AllowGuest READ allowGuest) + bool allowGuest() const; + + Q_PROPERTY(QString GuestIcon READ guestIcon) + QString guestIcon() const; + + Q_PROPERTY(QStringList UserList READ userList) + QStringList userList() const; + +public Q_SLOTS: // METHODS + void AllowGuestAccount(bool in0); + QString CreateGuestAccount(); + QDBusObjectPath CreateUser(const QString &in0, const QString &in1, int in2); + void DeleteUser(const QString &in0, bool in1); + QString FindUserById(const QString &in0); + QString FindUserByName(const QString &in0); + QStringList GetGroups(); + QStringList GetPresetGroups(int in0); + bool IsPasswordValid(const QString &in0, QString &out1, int &out2); + bool IsUsernameValid(const QString &in0, QString &out1, int &out2); + QString RandUserIcon(); +Q_SIGNALS: // SIGNALS + void UserAdded(const QString &in0); + void UserDeleted(const QString &in0); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.cpp new file mode 100644 index 00000000..9da00812 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.cpp @@ -0,0 +1,139 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Authenticate1.Session2.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class SessionAdaptor + */ + +SessionAdaptor::SessionAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +SessionAdaptor::~SessionAdaptor() +{ + // destructor +} + +MFAInfoList SessionAdaptor::factorsInfo() const +{ + // get the value of property FactorsInfo + return qvariant_cast< MFAInfoList >(parent()->property("FactorsInfo")); +} + +bool SessionAdaptor::isFuzzyMFA() const +{ + // get the value of property IsFuzzyMFA + return qvariant_cast< bool >(parent()->property("IsFuzzyMFA")); +} + +bool SessionAdaptor::isMFA() const +{ + // get the value of property IsMFA + return qvariant_cast< bool >(parent()->property("IsMFA")); +} + +int SessionAdaptor::pINLen() const +{ + // get the value of property PINLen + return qvariant_cast< int >(parent()->property("PINLen")); +} + +QString SessionAdaptor::prompt() const +{ + // get the value of property Prompt + return qvariant_cast< QString >(parent()->property("Prompt")); +} + +QString SessionAdaptor::username() const +{ + // get the value of property Username + return qvariant_cast< QString >(parent()->property("Username")); +} + +int SessionAdaptor::EncryptKey(int encryptType, ArrayInt encryptMethod, ArrayInt &encryptMethod_, QString &publicKey) +{ + // handle method call org.deepin.dde.Authenticate1.Session.EncryptKey + //return static_cast(parent())->EncryptKey(encryptType, encryptMethod, encryptMethod_, publicKey); +} + +int SessionAdaptor::End(int flag) +{ + // handle method call org.deepin.dde.Authenticate1.Session.End + int failNum; + QMetaObject::invokeMethod(parent(), "End", Q_RETURN_ARG(int, failNum), Q_ARG(int, flag)); + return failNum; +} + +int SessionAdaptor::GetResult() +{ + // handle method call org.deepin.dde.Authenticate1.Session.GetResult + int result; + QMetaObject::invokeMethod(parent(), "GetResult", Q_RETURN_ARG(int, result)); + return result; +} + +void SessionAdaptor::PrivilegesDisable() +{ + // handle method call org.deepin.dde.Authenticate1.Session.PrivilegesDisable + QMetaObject::invokeMethod(parent(), "PrivilegesDisable"); +} + +bool SessionAdaptor::PrivilegesEnable(const QString &path) +{ + // handle method call org.deepin.dde.Authenticate1.Session.PrivilegesEnable + bool enabled; + QMetaObject::invokeMethod(parent(), "PrivilegesEnable", Q_RETURN_ARG(bool, enabled), Q_ARG(QString, path)); + return enabled; +} + +void SessionAdaptor::Quit() +{ + // handle method call org.deepin.dde.Authenticate1.Session.Quit + QMetaObject::invokeMethod(parent(), "Quit"); +} + +void SessionAdaptor::SetQuitFlag(int flag) +{ + // handle method call org.deepin.dde.Authenticate1.Session.SetQuitFlag + QMetaObject::invokeMethod(parent(), "SetQuitFlag", Q_ARG(int, flag)); +} + +void SessionAdaptor::SetSymmetricKey(const QByteArray &key) +{ + // handle method call org.deepin.dde.Authenticate1.Session.SetSymmetricKey + QMetaObject::invokeMethod(parent(), "SetSymmetricKey", Q_ARG(QByteArray, key)); +} + +void SessionAdaptor::SetToken(int flag, const QByteArray &token) +{ + // handle method call org.deepin.dde.Authenticate1.Session.SetToken + QMetaObject::invokeMethod(parent(), "SetToken", Q_ARG(int, flag), Q_ARG(QByteArray, token)); +} + +int SessionAdaptor::Start(int flag, int timeout) +{ + // handle method call org.deepin.dde.Authenticate1.Session.Start + int state; + QMetaObject::invokeMethod(parent(), "Start", Q_RETURN_ARG(int, state), Q_ARG(int, flag), Q_ARG(int, timeout)); + return state; +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.h new file mode 100644 index 00000000..857a1eca --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor.h @@ -0,0 +1,126 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Authenticate1.Session2.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_AUTHENTICATE1_SESSION2ADAPTOR_H +#define ORG_DEEPIN_DDE_AUTHENTICATE1_SESSION2ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.Session2.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Authenticate1.Session + */ +class SessionAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Authenticate1.Session") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + SessionAdaptor(QObject *parent); + virtual ~SessionAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(MFAInfoList FactorsInfo READ factorsInfo) + MFAInfoList factorsInfo() const; + + Q_PROPERTY(bool IsFuzzyMFA READ isFuzzyMFA) + bool isFuzzyMFA() const; + + Q_PROPERTY(bool IsMFA READ isMFA) + bool isMFA() const; + + Q_PROPERTY(int PINLen READ pINLen) + int pINLen() const; + + Q_PROPERTY(QString Prompt READ prompt) + QString prompt() const; + + Q_PROPERTY(QString Username READ username) + QString username() const; + +public Q_SLOTS: // METHODS + int EncryptKey(int encryptType, ArrayInt encryptMethod, ArrayInt &encryptMethod_, QString &publicKey); + int End(int flag); + int GetResult(); + void PrivilegesDisable(); + bool PrivilegesEnable(const QString &path); + void Quit(); + void SetQuitFlag(int flag); + void SetSymmetricKey(const QByteArray &key); + void SetToken(int flag, const QByteArray &token); + int Start(int flag, int timeout); +Q_SIGNALS: // SIGNALS + void Status(int flag, int status, const QString &msg); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.cpp new file mode 100644 index 00000000..39ee5720 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.cpp @@ -0,0 +1,77 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Authenticate1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class Authenticate1Adaptor + */ + +Authenticate1Adaptor::Authenticate1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +Authenticate1Adaptor::~Authenticate1Adaptor() +{ + // destructor +} + +int Authenticate1Adaptor::frameworkState() const +{ + // get the value of property FrameworkState + return qvariant_cast< int >(parent()->property("FrameworkState")); +} + +QString Authenticate1Adaptor::supportEncrypts() const +{ + // get the value of property SupportEncrypts + return qvariant_cast< QString >(parent()->property("SupportEncrypts")); +} + +int Authenticate1Adaptor::supportedFlags() const +{ + // get the value of property SupportedFlags + return qvariant_cast< int >(parent()->property("SupportedFlags")); +} + +QString Authenticate1Adaptor::Authenticate(const QString &username, int authFlags, int appType) +{ + // handle method call org.deepin.dde.Authenticate1.Authenticate + QString path; + QMetaObject::invokeMethod(parent(), "Authenticate", Q_RETURN_ARG(QString, path), Q_ARG(QString, username), Q_ARG(int, authFlags), Q_ARG(int, appType)); + return path; +} + +QString Authenticate1Adaptor::GetLimits(const QString &username) +{ + // handle method call org.deepin.dde.Authenticate1.GetLimits + QString limits; + QMetaObject::invokeMethod(parent(), "GetLimits", Q_RETURN_ARG(QString, limits), Q_ARG(QString, username)); + return limits; +} + +QString Authenticate1Adaptor::PreOneKeyLogin(int flag) +{ + // handle method call org.deepin.dde.Authenticate1.PreOneKeyLogin + QString result; + QMetaObject::invokeMethod(parent(), "PreOneKeyLogin", Q_RETURN_ARG(QString, result), Q_ARG(int, flag)); + return result; +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.h new file mode 100644 index 00000000..2847b36f --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor.h @@ -0,0 +1,80 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Authenticate1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_AUTHENTICATE1ADAPTOR_H +#define ORG_DEEPIN_DDE_AUTHENTICATE1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Authenticate1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Authenticate1 + */ +class Authenticate1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Authenticate1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + Authenticate1Adaptor(QObject *parent); + virtual ~Authenticate1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(int FrameworkState READ frameworkState) + int frameworkState() const; + + Q_PROPERTY(QString SupportEncrypts READ supportEncrypts) + QString supportEncrypts() const; + + Q_PROPERTY(int SupportedFlags READ supportedFlags) + int supportedFlags() const; + +public Q_SLOTS: // METHODS + QString Authenticate(const QString &username, int authFlags, int appType); + QString GetLimits(const QString &username); + QString PreOneKeyLogin(int flag); +Q_SIGNALS: // SIGNALS + void LimitUpdated(const QString &in0); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.cpp new file mode 100644 index 00000000..59f9569c --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.cpp @@ -0,0 +1,49 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.ImageEffect1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class ImageEffect1Adaptor + */ + +ImageEffect1Adaptor::ImageEffect1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +ImageEffect1Adaptor::~ImageEffect1Adaptor() +{ + // destructor +} + +void ImageEffect1Adaptor::Delete(const QString &effect, const QString &filename) +{ + // handle method call org.deepin.dde.ImageEffect1.Delete + QMetaObject::invokeMethod(parent(), "Delete", Q_ARG(QString, effect), Q_ARG(QString, filename)); +} + +QString ImageEffect1Adaptor::Get(const QString &effect, const QString &filename) +{ + // handle method call org.deepin.dde.ImageEffect1.Get + QString outputFile; + QMetaObject::invokeMethod(parent(), "Get", Q_RETURN_ARG(QString, outputFile), Q_ARG(QString, effect), Q_ARG(QString, filename)); + return outputFile; +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.h new file mode 100644 index 00000000..cbe08341 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor.h @@ -0,0 +1,58 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.ImageEffect1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_IMAGEEFFECT1ADAPTOR_H +#define ORG_DEEPIN_DDE_IMAGEEFFECT1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.ImageEffect1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.ImageEffect1 + */ +class ImageEffect1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.ImageEffect1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + ImageEffect1Adaptor(QObject *parent); + virtual ~ImageEffect1Adaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void Delete(const QString &effect, const QString &filename); + QString Get(const QString &effect, const QString &filename); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.cpp new file mode 100644 index 00000000..31fc4b29 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.cpp @@ -0,0 +1,47 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Logined.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Logined.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class LoginedAdaptor + */ + +LoginedAdaptor::LoginedAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +LoginedAdaptor::~LoginedAdaptor() +{ + // destructor +} + +uint LoginedAdaptor::lastLogoutUser() const +{ + // get the value of property LastLogoutUser + return qvariant_cast< uint >(parent()->property("LastLogoutUser")); +} + +QString LoginedAdaptor::userList() const +{ + // get the value of property UserList + return qvariant_cast< QString >(parent()->property("UserList")); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.h new file mode 100644 index 00000000..c9323141 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor.h @@ -0,0 +1,55 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.Logined.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.LoginedAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Logined.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_LOGINEDADAPTOR_H +#define ORG_DEEPIN_DDE_LOGINEDADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.Logined.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Logined + */ +class LoginedAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Logined") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" + "") +public: + LoginedAdaptor(QObject *parent); + virtual ~LoginedAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(uint LastLogoutUser READ lastLogoutUser) + uint lastLogoutUser() const; + + Q_PROPERTY(QString UserList READ userList) + QString userList() const; + +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.cpp new file mode 100644 index 00000000..59930546 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.cpp @@ -0,0 +1,67 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.PowerManager1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class PowerManager1Adaptor + */ + +PowerManager1Adaptor::PowerManager1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +PowerManager1Adaptor::~PowerManager1Adaptor() +{ + // destructor +} + +bool PowerManager1Adaptor::CanHibernate() +{ + // handle method call org.deepin.dde.PowerManager1.CanHibernate + bool out0; + QMetaObject::invokeMethod(parent(), "CanHibernate", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool PowerManager1Adaptor::CanReboot() +{ + // handle method call org.deepin.dde.PowerManager1.CanReboot + bool out0; + QMetaObject::invokeMethod(parent(), "CanReboot", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool PowerManager1Adaptor::CanShutdown() +{ + // handle method call org.deepin.dde.PowerManager1.CanShutdown + bool out0; + QMetaObject::invokeMethod(parent(), "CanShutdown", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool PowerManager1Adaptor::CanSuspend() +{ + // handle method call org.deepin.dde.PowerManager1.CanSuspend + bool out0; + QMetaObject::invokeMethod(parent(), "CanSuspend", Q_RETURN_ARG(bool, out0)); + return out0; +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.h new file mode 100644 index 00000000..c3165d45 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor.h @@ -0,0 +1,63 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.PowerManager1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_POWERMANAGER1ADAPTOR_H +#define ORG_DEEPIN_DDE_POWERMANAGER1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.PowerManager1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.PowerManager1 + */ +class PowerManager1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.PowerManager1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + PowerManager1Adaptor(QObject *parent); + virtual ~PowerManager1Adaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + bool CanHibernate(); + bool CanReboot(); + bool CanShutdown(); + bool CanSuspend(); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.cpp new file mode 100644 index 00000000..04ac8aea --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.cpp @@ -0,0 +1,199 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SessionManager1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class SessionManager1Adaptor + */ + +SessionManager1Adaptor::SessionManager1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +SessionManager1Adaptor::~SessionManager1Adaptor() +{ + // destructor +} + +QString SessionManager1Adaptor::currentUid() const +{ + // get the value of property CurrentUid + return qvariant_cast< QString >(parent()->property("CurrentUid")); +} + +bool SessionManager1Adaptor::locked() const +{ + // get the value of property Locked + return qvariant_cast< bool >(parent()->property("Locked")); +} + +int SessionManager1Adaptor::stage() const +{ + // get the value of property Stage + return qvariant_cast< int >(parent()->property("Stage")); +} + +bool SessionManager1Adaptor::AllowSessionDaemonRun() +{ + // handle method call org.deepin.dde.SessionManager1.AllowSessionDaemonRun + bool out0; + QMetaObject::invokeMethod(parent(), "AllowSessionDaemonRun", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool SessionManager1Adaptor::CanHibernate() +{ + // handle method call org.deepin.dde.SessionManager1.CanHibernate + bool out0; + QMetaObject::invokeMethod(parent(), "CanHibernate", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool SessionManager1Adaptor::CanLogout() +{ + // handle method call org.deepin.dde.SessionManager1.CanLogout + bool out0; + QMetaObject::invokeMethod(parent(), "CanLogout", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool SessionManager1Adaptor::CanReboot() +{ + // handle method call org.deepin.dde.SessionManager1.CanReboot + bool out0; + QMetaObject::invokeMethod(parent(), "CanReboot", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool SessionManager1Adaptor::CanShutdown() +{ + // handle method call org.deepin.dde.SessionManager1.CanShutdown + bool out0; + QMetaObject::invokeMethod(parent(), "CanShutdown", Q_RETURN_ARG(bool, out0)); + return out0; +} + +bool SessionManager1Adaptor::CanSuspend() +{ + // handle method call org.deepin.dde.SessionManager1.CanSuspend + bool out0; + QMetaObject::invokeMethod(parent(), "CanSuspend", Q_RETURN_ARG(bool, out0)); + return out0; +} + +void SessionManager1Adaptor::ForceLogout() +{ + // handle method call org.deepin.dde.SessionManager1.ForceLogout + QMetaObject::invokeMethod(parent(), "ForceLogout"); +} + +void SessionManager1Adaptor::ForceReboot() +{ + // handle method call org.deepin.dde.SessionManager1.ForceReboot + QMetaObject::invokeMethod(parent(), "ForceReboot"); +} + +void SessionManager1Adaptor::ForceShutdown() +{ + // handle method call org.deepin.dde.SessionManager1.ForceShutdown + QMetaObject::invokeMethod(parent(), "ForceShutdown"); +} + +void SessionManager1Adaptor::Logout() +{ + // handle method call org.deepin.dde.SessionManager1.Logout + QMetaObject::invokeMethod(parent(), "Logout"); +} + +void SessionManager1Adaptor::PowerOffChoose() +{ + // handle method call org.deepin.dde.SessionManager1.PowerOffChoose + QMetaObject::invokeMethod(parent(), "PowerOffChoose"); +} + +void SessionManager1Adaptor::Reboot() +{ + // handle method call org.deepin.dde.SessionManager1.Reboot + QMetaObject::invokeMethod(parent(), "Reboot"); +} + +bool SessionManager1Adaptor::Register(const QString &in0) +{ + // handle method call org.deepin.dde.SessionManager1.Register + bool out0; + QMetaObject::invokeMethod(parent(), "Register", Q_RETURN_ARG(bool, out0), Q_ARG(QString, in0)); + return out0; +} + +void SessionManager1Adaptor::RequestHibernate() +{ + // handle method call org.deepin.dde.SessionManager1.RequestHibernate + QMetaObject::invokeMethod(parent(), "RequestHibernate"); +} + +void SessionManager1Adaptor::RequestLock() +{ + // handle method call org.deepin.dde.SessionManager1.RequestLock + QMetaObject::invokeMethod(parent(), "RequestLock"); +} + +void SessionManager1Adaptor::RequestLogout() +{ + // handle method call org.deepin.dde.SessionManager1.RequestLogout + QMetaObject::invokeMethod(parent(), "RequestLogout"); +} + +void SessionManager1Adaptor::RequestReboot() +{ + // handle method call org.deepin.dde.SessionManager1.RequestReboot + QMetaObject::invokeMethod(parent(), "RequestReboot"); +} + +void SessionManager1Adaptor::RequestShutdown() +{ + // handle method call org.deepin.dde.SessionManager1.RequestShutdown + QMetaObject::invokeMethod(parent(), "RequestShutdown"); +} + +void SessionManager1Adaptor::RequestSuspend() +{ + // handle method call org.deepin.dde.SessionManager1.RequestSuspend + QMetaObject::invokeMethod(parent(), "RequestSuspend"); +} + +void SessionManager1Adaptor::SetLocked(bool in0) +{ + // handle method call org.deepin.dde.SessionManager1.SetLocked + QMetaObject::invokeMethod(parent(), "SetLocked", Q_ARG(bool, in0)); +} + +void SessionManager1Adaptor::Shutdown() +{ + // handle method call org.deepin.dde.SessionManager1.Shutdown + QMetaObject::invokeMethod(parent(), "Shutdown"); +} + +void SessionManager1Adaptor::ToggleDebug() +{ + // handle method call org.deepin.dde.SessionManager1.ToggleDebug + QMetaObject::invokeMethod(parent(), "ToggleDebug"); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.h new file mode 100644 index 00000000..90e21708 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor.h @@ -0,0 +1,122 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SessionManager1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_SESSIONMANAGER1ADAPTOR_H +#define ORG_DEEPIN_DDE_SESSIONMANAGER1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SessionManager1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.SessionManager1 + */ +class SessionManager1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.SessionManager1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + SessionManager1Adaptor(QObject *parent); + virtual ~SessionManager1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(QString CurrentUid READ currentUid) + QString currentUid() const; + + Q_PROPERTY(bool Locked READ locked) + bool locked() const; + + Q_PROPERTY(int Stage READ stage) + int stage() const; + +public Q_SLOTS: // METHODS + bool AllowSessionDaemonRun(); + bool CanHibernate(); + bool CanLogout(); + bool CanReboot(); + bool CanShutdown(); + bool CanSuspend(); + void ForceLogout(); + void ForceReboot(); + void ForceShutdown(); + void Logout(); + void PowerOffChoose(); + void Reboot(); + bool Register(const QString &in0); + void RequestHibernate(); + void RequestLock(); + void RequestLogout(); + void RequestReboot(); + void RequestShutdown(); + void RequestSuspend(); + void SetLocked(bool in0); + void Shutdown(); + void ToggleDebug(); +Q_SIGNALS: // SIGNALS + void Unlock(); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.cpp new file mode 100644 index 00000000..0aeee5a4 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.cpp @@ -0,0 +1,77 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SoundThemePlayer1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class SoundThemePlayer1Adaptor + */ + +SoundThemePlayer1Adaptor::SoundThemePlayer1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +SoundThemePlayer1Adaptor::~SoundThemePlayer1Adaptor() +{ + // destructor +} + +void SoundThemePlayer1Adaptor::EnableSound(const QString &name, bool enabled) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.EnableSound + QMetaObject::invokeMethod(parent(), "EnableSound", Q_ARG(QString, name), Q_ARG(bool, enabled)); +} + +void SoundThemePlayer1Adaptor::EnableSoundDesktopLogin(bool enabled) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.EnableSoundDesktopLogin + QMetaObject::invokeMethod(parent(), "EnableSoundDesktopLogin", Q_ARG(bool, enabled)); +} + +void SoundThemePlayer1Adaptor::Play(const QString &theme, const QString &event, const QString &device) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.Play + QMetaObject::invokeMethod(parent(), "Play", Q_ARG(QString, theme), Q_ARG(QString, event), Q_ARG(QString, device)); +} + +void SoundThemePlayer1Adaptor::PlaySoundDesktopLogin() +{ + // handle method call org.deepin.dde.SoundThemePlayer1.PlaySoundDesktopLogin + QMetaObject::invokeMethod(parent(), "PlaySoundDesktopLogin"); +} + +void SoundThemePlayer1Adaptor::PrepareShutdownSound(int uid) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.PrepareShutdownSound + QMetaObject::invokeMethod(parent(), "PrepareShutdownSound", Q_ARG(int, uid)); +} + +void SoundThemePlayer1Adaptor::SaveAudioState(const QVariantMap &avtivePlayback) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.SaveAudioState + QMetaObject::invokeMethod(parent(), "SaveAudioState", Q_ARG(QVariantMap, avtivePlayback)); +} + +void SoundThemePlayer1Adaptor::SetSoundTheme(const QString &theme) +{ + // handle method call org.deepin.dde.SoundThemePlayer1.SetSoundTheme + QMetaObject::invokeMethod(parent(), "SetSoundTheme", Q_ARG(QString, theme)); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.h new file mode 100644 index 00000000..06e56eca --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor.h @@ -0,0 +1,77 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SoundThemePlayer1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_SOUNDTHEMEPLAYER1ADAPTOR_H +#define ORG_DEEPIN_DDE_SOUNDTHEMEPLAYER1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SoundThemePlayer1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.SoundThemePlayer1 + */ +class SoundThemePlayer1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.SoundThemePlayer1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + SoundThemePlayer1Adaptor(QObject *parent); + virtual ~SoundThemePlayer1Adaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void EnableSound(const QString &name, bool enabled); + void EnableSoundDesktopLogin(bool enabled); + void Play(const QString &theme, const QString &event, const QString &device); + void PlaySoundDesktopLogin(); + void PrepareShutdownSound(int uid); + void SaveAudioState(const QVariantMap &avtivePlayback); + void SetSoundTheme(const QString &theme); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.cpp new file mode 100644 index 00000000..2e38e70c --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.cpp @@ -0,0 +1,49 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SystemDisplay1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class Display1Adaptor + */ + +Display1Adaptor::Display1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +Display1Adaptor::~Display1Adaptor() +{ + // destructor +} + +QString Display1Adaptor::GetConfig() +{ + // handle method call org.deepin.dde.Display1.GetConfig + QString out0; + QMetaObject::invokeMethod(parent(), "GetConfig", Q_RETURN_ARG(QString, out0)); + return out0; +} + +void Display1Adaptor::SetConfig(const QString &in0) +{ + // handle method call org.deepin.dde.Display1.SetConfig + QMetaObject::invokeMethod(parent(), "SetConfig", Q_ARG(QString, in0)); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.h new file mode 100644 index 00000000..b4b57f4b --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor.h @@ -0,0 +1,59 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SystemDisplay1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_SYSTEMDISPLAY1ADAPTOR_H +#define ORG_DEEPIN_DDE_SYSTEMDISPLAY1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemDisplay1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Display1 + */ +class Display1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Display1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + Display1Adaptor(QObject *parent); + virtual ~Display1Adaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + QString GetConfig(); + void SetConfig(const QString &in0); +Q_SIGNALS: // SIGNALS + void ConfigUpdated(const QString &in0); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.cpp b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.cpp new file mode 100644 index 00000000..f75d0032 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.cpp @@ -0,0 +1,181 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SystemPower1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class Power1Adaptor + */ + +Power1Adaptor::Power1Adaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +Power1Adaptor::~Power1Adaptor() +{ + // destructor +} + +double Power1Adaptor::batteryPercentage() const +{ + // get the value of property BatteryPercentage + return qvariant_cast< double >(parent()->property("BatteryPercentage")); +} + +uint Power1Adaptor::batteryStatus() const +{ + // get the value of property BatteryStatus + return qvariant_cast< uint >(parent()->property("BatteryStatus")); +} + +qulonglong Power1Adaptor::batteryTimeToEmpty() const +{ + // get the value of property BatteryTimeToEmpty + return qvariant_cast< qulonglong >(parent()->property("BatteryTimeToEmpty")); +} + +qulonglong Power1Adaptor::batteryTimeToFull() const +{ + // get the value of property BatteryTimeToFull + return qvariant_cast< qulonglong >(parent()->property("BatteryTimeToFull")); +} + +bool Power1Adaptor::hasBattery() const +{ + // get the value of property HasBattery + return qvariant_cast< bool >(parent()->property("HasBattery")); +} + +bool Power1Adaptor::hasLidSwitch() const +{ + // get the value of property HasLidSwitch + return qvariant_cast< bool >(parent()->property("HasLidSwitch")); +} + +bool Power1Adaptor::isHighPerformanceSupported() const +{ + // get the value of property IsHighPerformanceSupported + return qvariant_cast< bool >(parent()->property("IsHighPerformanceSupported")); +} + +QString Power1Adaptor::mode() const +{ + // get the value of property Mode + return qvariant_cast< QString >(parent()->property("Mode")); +} + +bool Power1Adaptor::onBattery() const +{ + // get the value of property OnBattery + return qvariant_cast< bool >(parent()->property("OnBattery")); +} + +bool Power1Adaptor::powerSavingModeAuto() const +{ + // get the value of property PowerSavingModeAuto + return qvariant_cast< bool >(parent()->property("PowerSavingModeAuto")); +} + +void Power1Adaptor::setPowerSavingModeAuto(bool value) +{ + // set the value of property PowerSavingModeAuto + parent()->setProperty("PowerSavingModeAuto", QVariant::fromValue(value)); +} + +bool Power1Adaptor::powerSavingModeAutoWhenBatteryLow() const +{ + // get the value of property PowerSavingModeAutoWhenBatteryLow + return qvariant_cast< bool >(parent()->property("PowerSavingModeAutoWhenBatteryLow")); +} + +void Power1Adaptor::setPowerSavingModeAutoWhenBatteryLow(bool value) +{ + // set the value of property PowerSavingModeAutoWhenBatteryLow + parent()->setProperty("PowerSavingModeAutoWhenBatteryLow", QVariant::fromValue(value)); +} + +uint Power1Adaptor::powerSavingModeBrightnessDropPercent() const +{ + // get the value of property PowerSavingModeBrightnessDropPercent + return qvariant_cast< uint >(parent()->property("PowerSavingModeBrightnessDropPercent")); +} + +void Power1Adaptor::setPowerSavingModeBrightnessDropPercent(uint value) +{ + // set the value of property PowerSavingModeBrightnessDropPercent + parent()->setProperty("PowerSavingModeBrightnessDropPercent", QVariant::fromValue(value)); +} + +bool Power1Adaptor::powerSavingModeEnabled() const +{ + // get the value of property PowerSavingModeEnabled + return qvariant_cast< bool >(parent()->property("PowerSavingModeEnabled")); +} + +void Power1Adaptor::setPowerSavingModeEnabled(bool value) +{ + // set the value of property PowerSavingModeEnabled + parent()->setProperty("PowerSavingModeEnabled", QVariant::fromValue(value)); +} + +bool Power1Adaptor::powerSystemAutoToSleepWhenFree() const +{ + // get the value of property PowerSystemAutoToSleepWhenFree + return qvariant_cast< bool >(parent()->property("PowerSystemAutoToSleepWhenFree")); +} + +void Power1Adaptor::setPowerSystemAutoToSleepWhenFree(bool value) +{ + // set the value of property PowerSystemAutoToSleepWhenFree + parent()->setProperty("PowerSystemAutoToSleepWhenFree", QVariant::fromValue(value)); +} + +QList Power1Adaptor::GetBatteries() +{ + // handle method call org.deepin.dde.Power1.GetBatteries + QList batteries; + QMetaObject::invokeMethod(parent(), "GetBatteries", Q_RETURN_ARG(QList, batteries)); + return batteries; +} + +void Power1Adaptor::Refresh() +{ + // handle method call org.deepin.dde.Power1.Refresh + QMetaObject::invokeMethod(parent(), "Refresh"); +} + +void Power1Adaptor::RefreshBatteries() +{ + // handle method call org.deepin.dde.Power1.RefreshBatteries + QMetaObject::invokeMethod(parent(), "RefreshBatteries"); +} + +void Power1Adaptor::RefreshMains() +{ + // handle method call org.deepin.dde.Power1.RefreshMains + QMetaObject::invokeMethod(parent(), "RefreshMains"); +} + +void Power1Adaptor::SetMode(const QString &mode) +{ + // handle method call org.deepin.dde.Power1.SetMode + QMetaObject::invokeMethod(parent(), "SetMode", Q_ARG(QString, mode)); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.h b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.h new file mode 100644 index 00000000..57df7819 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor.h @@ -0,0 +1,138 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.deepin.dde.SystemPower1.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1Adaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_DEEPIN_DDE_SYSTEMPOWER1ADAPTOR_H +#define ORG_DEEPIN_DDE_SYSTEMPOWER1ADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.deepin.dde.SystemPower1.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.deepin.dde.Power1 + */ +class Power1Adaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.Power1") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + Power1Adaptor(QObject *parent); + virtual ~Power1Adaptor(); + +public: // PROPERTIES + Q_PROPERTY(double BatteryPercentage READ batteryPercentage) + double batteryPercentage() const; + + Q_PROPERTY(uint BatteryStatus READ batteryStatus) + uint batteryStatus() const; + + Q_PROPERTY(qulonglong BatteryTimeToEmpty READ batteryTimeToEmpty) + qulonglong batteryTimeToEmpty() const; + + Q_PROPERTY(qulonglong BatteryTimeToFull READ batteryTimeToFull) + qulonglong batteryTimeToFull() const; + + Q_PROPERTY(bool HasBattery READ hasBattery) + bool hasBattery() const; + + Q_PROPERTY(bool HasLidSwitch READ hasLidSwitch) + bool hasLidSwitch() const; + + Q_PROPERTY(bool IsHighPerformanceSupported READ isHighPerformanceSupported) + bool isHighPerformanceSupported() const; + + Q_PROPERTY(QString Mode READ mode) + QString mode() const; + + Q_PROPERTY(bool OnBattery READ onBattery) + bool onBattery() const; + + Q_PROPERTY(bool PowerSavingModeAuto READ powerSavingModeAuto WRITE setPowerSavingModeAuto) + bool powerSavingModeAuto() const; + void setPowerSavingModeAuto(bool value); + + Q_PROPERTY(bool PowerSavingModeAutoWhenBatteryLow READ powerSavingModeAutoWhenBatteryLow WRITE setPowerSavingModeAutoWhenBatteryLow) + bool powerSavingModeAutoWhenBatteryLow() const; + void setPowerSavingModeAutoWhenBatteryLow(bool value); + + Q_PROPERTY(uint PowerSavingModeBrightnessDropPercent READ powerSavingModeBrightnessDropPercent WRITE setPowerSavingModeBrightnessDropPercent) + uint powerSavingModeBrightnessDropPercent() const; + void setPowerSavingModeBrightnessDropPercent(uint value); + + Q_PROPERTY(bool PowerSavingModeEnabled READ powerSavingModeEnabled WRITE setPowerSavingModeEnabled) + bool powerSavingModeEnabled() const; + void setPowerSavingModeEnabled(bool value); + + Q_PROPERTY(bool PowerSystemAutoToSleepWhenFree READ powerSystemAutoToSleepWhenFree WRITE setPowerSystemAutoToSleepWhenFree) + bool powerSystemAutoToSleepWhenFree() const; + void setPowerSystemAutoToSleepWhenFree(bool value); + +public Q_SLOTS: // METHODS + QList GetBatteries(); + void Refresh(); + void RefreshBatteries(); + void RefreshMains(); + void SetMode(const QString &mode); +Q_SIGNALS: // SIGNALS + void BatteryAdded(const QDBusObjectPath &objpath); + void BatteryDisplayUpdate(qlonglong timestamp); + void BatteryRemoved(const QDBusObjectPath &objpath); + void LidClosed(); + void LidOpened(); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.cpp b/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.cpp new file mode 100644 index 00000000..ec6635ee --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.cpp @@ -0,0 +1,35 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.freedesktop.DBus.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBus.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class DBusAdaptor + */ + +DBusAdaptor::DBusAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +DBusAdaptor::~DBusAdaptor() +{ + // destructor +} + diff --git a/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.h b/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.h new file mode 100644 index 00000000..da03c5e7 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor.h @@ -0,0 +1,53 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.freedesktop.DBus.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBusAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBus.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_FREEDESKTOP_DBUSADAPTOR_H +#define ORG_FREEDESKTOP_DBUSADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.DBus.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.freedesktop.DBus + */ +class DBusAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.DBus") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + DBusAdaptor(QObject *parent); + virtual ~DBusAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS + void NameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); +}; + +#endif diff --git a/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.cpp b/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.cpp new file mode 100644 index 00000000..e4a87cb1 --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.cpp @@ -0,0 +1,89 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.freedesktop.login1.session.self.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.self.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class SessionAdaptor + */ + +SessionAdaptor::SessionAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +SessionAdaptor::~SessionAdaptor() +{ + // destructor +} + +bool SessionAdaptor::active() const +{ + // get the value of property Active + return qvariant_cast< bool >(parent()->property("Active")); +} + +QString SessionAdaptor::desktop() const +{ + // get the value of property Desktop + return qvariant_cast< QString >(parent()->property("Desktop")); +} + +QString SessionAdaptor::display() const +{ + // get the value of property Display + return qvariant_cast< QString >(parent()->property("Display")); +} + +QString SessionAdaptor::id() const +{ + // get the value of property Id + return qvariant_cast< QString >(parent()->property("Id")); +} + +QString SessionAdaptor::name() const +{ + // get the value of property Name + return qvariant_cast< QString >(parent()->property("Name")); +} + +void SessionAdaptor::Activate() +{ + // handle method call org.freedesktop.login1.Session.Activate + QMetaObject::invokeMethod(parent(), "Activate"); +} + +void SessionAdaptor::Lock() +{ + // handle method call org.freedesktop.login1.Session.Lock + QMetaObject::invokeMethod(parent(), "Lock"); +} + +void SessionAdaptor::Terminate() +{ + // handle method call org.freedesktop.login1.Session.Terminate + QMetaObject::invokeMethod(parent(), "Terminate"); +} + +void SessionAdaptor::Unlock() +{ + // handle method call org.freedesktop.login1.Session.Unlock + QMetaObject::invokeMethod(parent(), "Unlock"); +} + diff --git a/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.h b/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.h new file mode 100644 index 00000000..1be5d20a --- /dev/null +++ b/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor.h @@ -0,0 +1,76 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp ./dde-session-shell/xml/org.freedesktop.login1.session.self.xml -a ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.selfAdaptor -i ./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.self.h + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef ORG_FREEDESKTOP_LOGIN1_SESSION_SELFADAPTOR_H +#define ORG_FREEDESKTOP_LOGIN1_SESSION_SELFADAPTOR_H + +#include +#include +#include "./dde-session-shell/toolGenerate/qdbusxml2cpp/org.freedesktop.login1.session.self.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.freedesktop.login1.Session + */ +class SessionAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.login1.Session") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + SessionAdaptor(QObject *parent); + virtual ~SessionAdaptor(); + +public: // PROPERTIES + Q_PROPERTY(bool Active READ active) + bool active() const; + + Q_PROPERTY(QString Desktop READ desktop) + QString desktop() const; + + Q_PROPERTY(QString Display READ display) + QString display() const; + + Q_PROPERTY(QString Id READ id) + QString id() const; + + Q_PROPERTY(QString Name READ name) + QString name() const; + +public Q_SLOTS: // METHODS + void Activate(); + void Lock(); + void Terminate(); + void Unlock(); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/translations/dde-session-shell_ady.ts b/translations/dde-session-shell_ady.ts new file mode 100644 index 00000000..0351e106 --- /dev/null +++ b/translations/dde-session-shell_ady.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_af.ts b/translations/dde-session-shell_af.ts index 82fee00f..b3ae8b7c 100644 --- a/translations/dde-session-shell_af.ts +++ b/translations/dde-session-shell_af.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Skakel af + Verify your fingerprint + - - - - - Reboot + Verification successful - - - - Suspend - Opskort + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out + Fingerprint locked, use password please + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock + Verify your Iris ID - - Switch user + Iris ID locked, use password please - DeepinAuthFramework + AuthPasskey - - Verify your fingerprint or password + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Verkeerde Wagwoord - - The domain account or password is not correct. Please enter again. + Password + Wagwoord + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker + + Wrong account + + + + Wrong Password + Verkeerde Wagwoord + + InhibitWarnView - Cancel Kanselleer + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - Verkeerde Wagwoord - MultiUsersWarningView - Cancel Kanselleer - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Skakel af - - Reboot - - Suspend Opskort - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Wagwoord + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Skakel af + + + Reboot + + + + Suspend + Opskort + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_af_ZA.ts b/translations/dde-session-shell_af_ZA.ts new file mode 100644 index 00000000..bf3d2cd5 --- /dev/null +++ b/translations/dde-session-shell_af_ZA.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ak.ts b/translations/dde-session-shell_ak.ts index 1db6364d..a2b506c7 100644 --- a/translations/dde-session-shell_ak.ts +++ b/translations/dde-session-shell_ak.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot - Reboot + Verification successful + + + + Verification failed, %n chances left + - - - Suspend - Suspend + Verification failed, only one chance left + - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock - Lock + Iris ID locked, use password please + + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + Wrong Password + + + Password + Password + - - Verify your fingerprint or password + Please try again 1 minute later + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + - GreeterWorkek + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + Wrong Password + Wrong Password + InhibitWarnView - Cancel Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - + Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - - - Wrong Password - + Failed to match fingerprint MultiUsersWarningView - Cancel Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. ShutdownWidget - Shut down - + Shut down - - Reboot Reboot - - Suspend Suspend - - Hibernate + Hibernate + + + Lock + Lock + + + Log out + Log out + + + Switch user + Switch user + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot SystemMonitor - Start system monitor - + Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Shut down + + + Reboot + Reboot + + + Suspend + Suspend + + + Hibernate + Hibernate + + + Log out + Log out + + + Are you sure you want to shut down? + Are you sure you want to shut down? + + + Are you sure you want to reboot? + Are you sure you want to reboot? + + + Are you sure you want to log out? + Are you sure you want to log out? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_am.ts b/translations/dde-session-shell_am.ts new file mode 100644 index 00000000..6757e2ea --- /dev/null +++ b/translations/dde-session-shell_am.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_am_ET.ts b/translations/dde-session-shell_am_ET.ts index 96fe4d28..b9388683 100644 --- a/translations/dde-session-shell_am_ET.ts +++ b/translations/dde-session-shell_am_ET.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - ማጥፊያ + Verify your fingerprint + - - - - - Reboot - እንደገና ማስነሻ + Verification successful + - - - - Suspend - ማገጃ + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out - መውጫ + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - መቆለፊያ + Verify your Iris ID + - - Switch user - ተጠቃሚ መቀየሪያ + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + - - Verify your fingerprint or password + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password የተሳሳተ የመግቢያ ቃል - - The domain account or password is not correct. Please enter again. + Password + የ መግቢያ ቃል + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + የተሳሳተ የመግቢያ ቃል + InhibitWarnView - Cancel መሰረዣ + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint የ ጣት አሻራ ማመሳሰል አልተቻለም - - - Wrong Password - የተሳሳተ የመግቢያ ቃል - MultiUsersWarningView - Cancel መሰረዣ - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down ማጥፊያ - - Reboot እንደገና ማስነሻ - - Suspend ማገጃ - - Hibernate + + Lock + መቆለፊያ + + + Log out + መውጫ + + + Switch user + ተጠቃሚ መቀየሪያ + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor የ ስርአት መቆጣጠሪያ ማስጀመሪያ - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - የ መግቢያ ቃል እንደገና ይጻፉ + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - እባክዎን አዲስ የ መግቢያ ቃል ያስገቡ + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match + Please select the account for login + + + + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - የ መግቢያ ቃል + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - እንደገና ለማስጀመር የ እርስዎን የ መግቢያ ቃል ያስገቡ + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + ማጥፊያ + + + Reboot + እንደገና ማስነሻ + + + Suspend + ማገጃ + + + Hibernate + + + + Log out + መውጫ + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ar.ts b/translations/dde-session-shell_ar.ts index 024ee9ba..6dd8ba09 100644 --- a/translations/dde-session-shell_ar.ts +++ b/translations/dde-session-shell_ar.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - البرامج تمنع الحاسب الآلي من إيقاف التشغيل، وإجبارك لإيقاف التشغيل يمكن أن يتسبب بفقدك لبعض البيانات + Face ID + معرف الوجه - - - - - - To close the program, click Cancel, and then close the program. - لإغلاق البرنامج ، انقر على "إلغاء" ، ثم أغلق البرنامج. + Verification successful + تم التحقق بنجاح + + + Verification failed, %n chances left + فشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرص متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقية - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - البرامج تمنع الحاسب الآلي من إعادة التشغيل، وإجبارك لإعادة التشغيل يمكن أن يتسبب بفقدك لبعض البيانات + Verification failed, only one chance left + فشل التحقق، تبقى فرصة واحدة فقط - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - البرامج تمنع الحاسب الآلي من إيقاف التشغيل المؤقت، وإجبارك لإيقاف التشغيل المؤقت يمكن أن يتسبب بفقدك لبعض البيانات + Verify your Face ID + تحقق من معرف الوجه الخاص بك - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - البرامج تمنع الحاسب الآلي من الدخول لوضع السبات، وإجبارك للدخول لوضع السبات يمكن أن يتسبب بفقدك بعض البيانات + Face ID locked, use password please + تم قفل معرف الوجه، يرجى استخدام كلمة المرور - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - البرامج تمنع الحاسب الآلي من تسجيل الخروج، وإجبارك لتسجيل الخروج يمكن أن يتسبب بفقدك لبعض البيانات + Device unavailable! + الجهاز غير متاح! + + + AuthFingerprint - - - - - Shut down - إيقاف التشغيل + Verify your fingerprint + تحقق من بصمتك - - - - - Reboot - إعادة التشغيل + Verification successful + تم التحقق بنجاح + + + Verification failed, %n chances left + فشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرص متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقية - - - Suspend - إسبات + Verification failed, only one chance left + فشل التحقق، تبقى فرصة واحدة فقط - - - Hibernate - وضع السكون + Fingerprint locked, use password please + تم قفل البصمة، يرجى استخدام كلمة المرور + + + AuthIris - - - - Log out - تسجيل الخروج + Iris ID + معرف القزحية - - Are you sure you want to shut down? - هل أنت متأكد من إيقاف التشغيل؟ + Verification successful + تم التحقق بنجاح + + + Verification failed, %n chances left + فشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرص متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقية - - Are you sure you want to reboot? - هل أنت متأكد من إعادة التشغيل؟ + Verification failed, only one chance left + فشل التحقق، تبقى فرصة واحدة فقط - - Are you sure you want to log out? - هل أنت متأكد من تسجيل الخروج؟ + Verify your Iris ID + تحقق من معرف القزحية الخاص بك - - Lock - قفل + Iris ID locked, use password please + تم قفل معرف القزحية، يرجى استخدام كلمة المرور + + + AuthPasskey - - Switch user - تبديل المستخدم + Please plug in the security key + يرجى توصيل مفتاح الأمان - - Switch system - + Verification successful + تم التحقق بنجاح + + + Verification failed + فشل التحقق + + + Identifying the security key + جارٍ التعرف على مفتاح الأمان - GreeterWorkek + AuthPassword + + Verification successful + تم التحقق بنجاح + + + Verification failed, %n chances left + فشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرص متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقية + + + Verification failed, only one chance left + فشل التحقق، تبقى فرصة واحدة فقط + - Wrong Password كلمة مرور خاطئة - - The account or password is not correct. Please enter again. - + Password + كلمة المرور + + + Please try again 1 minute later + يرجى المحاولة مرة أخرى بعد دقيقة واحدة + + + Please try again %n minutes later + يرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقائقيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقة + + + Reset Password + إعادة تعيين كلمة المرور + + + Forgot password? + نسيت كلمة المرور؟ + + + + AuthSingle + + Please try again 1 minute later + يرجى المحاولة مرة أخرى بعد دقيقة واحدة + + + Please try again %n minutes later + يرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقائقيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقة + + + Reset Password + إعادة تعيين كلمة المرور + + + Forgot password? + نسيت كلمة المرور؟ + + + + AuthUKey + + Verification successful + تم التحقق بنجاح + + + Verification failed, %n chances left + فشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرص متبقيةفشل التحقق، %n فرصة متبقيةفشل التحقق، %n فرصة متبقية + + + Verification failed, only one chance left + فشل التحقق، تبقى فرصة واحدة فقط + + + Wrong PIN + رمز PIN خاطئ + + + UKey is required + مطلوب UKey + + + Enter your PIN + أدخل رمز PIN الخاص بك + + + Please try again %n minute(s) later + يرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقائقيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقة + + + Please try again 1 minute later + يرجى المحاولة مرة أخرى بعد دقيقة واحدة + + + Please try again %n minutes later + يرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقائقيرجى المحاولة مرة أخرى بعد %n دقيقةيرجى المحاولة مرة أخرى بعد %n دقيقة + + + + AuthWidget + + Account + حساب + + + Your password will expire in %n days, please change it timely + ستنتهي صلاحية كلمة المرور الخاصة بك خلال %n يوم، يرجى تغييرها في الوقت المناسبستنتهي صلاحية كلمة المرور الخاصة بك خلال %n يوم، يرجى تغييرها في الوقت المناسبستنتهي صلاحية كلمة المرور الخاصة بك خلال %n يوم، يرجى تغييرها في الوقت المناسبستنتهي صلاحية كلمة المرور الخاصة بك خلال %n أيام، يرجى تغييرها في الوقت المناسبستنتهي صلاحية كلمة المرور الخاصة بك خلال %n يومًا، يرجى تغييرها في الوقت المناسبستنتهي صلاحية كلمة المرور الخاصة بك خلال %n يوم، يرجى تغييرها في الوقت المناسب + + + Password expired, please change + انتهت صلاحية كلمة المرور، نرجوا تغييرها + + + Your password has expired. Please contact the administrator to change it + انتهت صلاحية كلمة المرور الخاصة بك. يرجى الاتصال بالمسؤول لتغييرها + + + Terminal locked, please contact administrator + تم قفل الطرفية، يرجى الاتصال بالمسؤول + + + + DeepinAuthFramework + + Wrong Password + كلمة مرور خاطئة + + + + GreeterWorker + + Wrong account + حساب خاطئ + + + Wrong Password + كلمة مرور خاطئة InhibitWarnView - Cancel إلغاء + + The reason of inhibit. + سبب المنع. + + + + LighterGreeter + + Standard Mode + الوضع القياسي + LockContent - Lock Screen قفل الشاشة - Failed to lock screen فشل إقفال الشاشة @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually نفذ وقت التحقق من البصمة ، رجاءً أدخل كلمة المرور يدويًا - Failed to match fingerprint فشل في مطابقة البصمة - - - Wrong Password - كلمة مرور خاطئة - MultiUsersWarningView - Cancel إلغاء - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? المستخدمون أعلاه لا يزالون قيد تسجيل الدخول وسيتم فقدان البيانات بسبب إيقاف التشغيل ، هل أنت متأكد من مواصلة إيقاف التشغيل ؟ - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? المستخدمون أعلاه لا يزالون قيد تسجيل الدخول وسيتم فقدان البيانات بسبب إعادة التشغيل ، هل أنت متأكد من مواصلة إعادة التشغيل ؟ + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + لقد قمت بتمكين مستوى الأمان العالي للنظام، لذا لا يمكن التبديل إلى وضع Wayland، يرجى تعطيل مستوى الأمان العالي في مركز الأمان والمحاولة مرة أخرى. + + ShutdownWidget - Shut down إيقاف التشغيل - - Reboot إعادة التشغيل - - Suspend إسبات - - Hibernate وضع السكون + + Lock + قفل + + + Log out + تسجيل الخروج + + + Switch user + تبديل المستخدم + + + Switch system + تبديل النظام + + + Update and Shut Down + تحديث وإيقاف التشغيل + + + Update and Reboot + تحديث وإعادة التشغيل + SystemMonitor - Start system monitor بدء مراقب النظام - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - انتهت صلاحية كلمة المرور، نرجوا تغييرها + 发送验证码 + إرسال رمز التحقق + + + 请输入手机号 + يرجى إدخال رقم الهاتف - - New password - كلمة المرور الجديدة + 请输入验证码 + يرجى إدخال رمز التحقق - - Repeat password - كرر كلمة المرور + 获取验证码 + الحصول على رمز التحقق + + + + UpdateWorker + + Update + تحديث - - Failed to change your password - لم يتم تغيير كلمة المرور + Please plug in and then install updates. + يرجى التوصيل ثم تثبيت التحديثات. + + + UsersWithTheSameName - - Password too weak - كلمة المرور ضعيفة جداً + Return + رجوع - - Please enter the new password - يرجى إدخال كلمة المرور الجديدة + Please select the account for login + يرجى اختيار الحساب لتسجيل الدخول - - Please repeat the new password - الرجاء إعادة إدخال كلمة المرور الجديدة + Local Account + حساب محلي - - Passwords do not match - كلمتا المرور غير متطابقتان + Domain Account + حساب مجال - UserLoginWidget + WarningContent - - Password - كلمة المرور + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + البرامج تمنع الحاسب الآلي من إيقاف التشغيل، وإجبارك لإيقاف التشغيل يمكن أن يتسبب بفقدك لبعض البيانات - - Account - حساب + To close the program, click Cancel, and then close the program. + لإغلاق البرنامج ، انقر على "إلغاء" ، ثم أغلق البرنامج. - - Please enter the account - نرجوا إدخال الحساب + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + البرامج تمنع الحاسب الآلي من إعادة التشغيل، وإجبارك لإعادة التشغيل يمكن أن يتسبب بفقدك لبعض البيانات - - Please enter the password - نرجوا إدخال كلمة المرور + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + البرامج تمنع الحاسب الآلي من إيقاف التشغيل المؤقت، وإجبارك لإيقاف التشغيل المؤقت يمكن أن يتسبب بفقدك لبعض البيانات - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + البرامج تمنع الحاسب الآلي من الدخول لوضع السبات، وإجبارك للدخول لوضع السبات يمكن أن يتسبب بفقدك بعض البيانات + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + البرامج تمنع الحاسب الآلي من تسجيل الخروج، وإجبارك لتسجيل الخروج يمكن أن يتسبب بفقدك لبعض البيانات + + + Shut down + إيقاف التشغيل + + + Reboot + إعادة التشغيل + + + Suspend + إسبات + + + Hibernate + وضع السكون + + + Log out + تسجيل الخروج + + + Are you sure you want to shut down? + هل أنت متأكد من إيقاف التشغيل؟ + + + Are you sure you want to reboot? + هل أنت متأكد من إعادة التشغيل؟ + + + Are you sure you want to log out? + هل أنت متأكد من تسجيل الخروج؟ + + + Update and Shut Down + تحديث وإيقاف التشغيل + + + Update and Reboot + تحديث وإعادة التشغيل + + + Closing the programs and shutting down, please wait... + جارٍ إغلاق البرامج وإيقاف التشغيل، يرجى الانتظار... + + + Closing the programs and rebooting, please wait... + جارٍ إغلاق البرامج وإعادة التشغيل، يرجى الانتظار... + + + Closing the programs and logging out, please wait... + جارٍ إغلاق البرامج وتسجيل الخروج، يرجى الانتظار... + + + + dss::module::AssistLoginWidget + + Automatic login + تسجيل الدخول التلقائي + + + + dss::module::NetworkModule + + Turn on + تشغيل + + + Turn off + ايقاف \ No newline at end of file diff --git a/translations/dde-session-shell_ar_EG.ts b/translations/dde-session-shell_ar_EG.ts new file mode 100644 index 00000000..185681b4 --- /dev/null +++ b/translations/dde-session-shell_ar_EG.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + أغلق + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + أغلق + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ast.ts b/translations/dde-session-shell_ast.ts index d0f8d3b3..0bd416e6 100644 --- a/translations/dde-session-shell_ast.ts +++ b/translations/dde-session-shell_ast.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Apagar + Verify your fingerprint + - - - - - Reboot - Reaniciar + Verification successful + - - - - Suspend - Suspender + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out - Zarrar sesión + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - Bloquiar + Verify your Iris ID + - - Switch user - Camudar d'usuariu + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + - - Verify your fingerprint or password + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Contraseña incorreuta - - The domain account or password is not correct. Please enter again. + Password + Contraseña + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + Contraseña incorreuta + InhibitWarnView - Cancel Encaboxar + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - Contraseña incorreuta - MultiUsersWarningView - Cancel Encaboxar - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Apagar - - Reboot Reaniciar - - Suspend Suspender - - Hibernate + + Lock + Bloquiar + + + Log out + Zarrar sesión + + + Switch user + Camudar d'usuariu + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Aniciar monitor del sistema - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - Repitir contraseña + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - Introduz la contraseña nueva, por favor + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match + Please select the account for login + + + + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - Contraseña + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Introduz la contraseña pa reaniciar + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Apagar + + + Reboot + Reaniciar + + + Suspend + Suspender + + + Hibernate + + + + Log out + Zarrar sesión + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_az.ts b/translations/dde-session-shell_az.ts index ff8ec2a2..7d14a492 100644 --- a/translations/dde-session-shell_az.ts +++ b/translations/dde-session-shell_az.ts @@ -27,7 +27,7 @@ Device unavailable! - + Cihaz əlçatmazdır @@ -80,6 +80,25 @@ İris İD kilidləndi, lütfən şifrədən istifadə edin + + AuthPasskey + + Please plug in the security key + Təhlükəsizlik açarını qoşun + + + Verification successful + Doğrulama uğurlu oldu + + + Verification failed + Doğrulama alınmadı + + + Identifying the security key + Təhlükəsizlik açarı müəyyənləşdirilir + + AuthPassword @@ -108,7 +127,7 @@ Please try again %n minutes later - Lütfən %n dəqiqə sonra cəhd edinLütfən %n dəqiqə sonra cəhd edin + Lütfən, %n dəqiqə sonra yenidən cəhd edinLütfən %n dəqiqə sonra yenidən cəhd edin Reset Password @@ -174,7 +193,7 @@ Please try again %n minutes later - Lütfən %n dəqiqə sonra cəhd edinLütfən %n dəqiqə sonra cəhd edin + Lütfən %n dəqiqə sonra yenidən cəhd edinLütfən %n dəqiqə sonra yenidən cəhd edin @@ -191,6 +210,21 @@ Password expired, please change Şifrənin vaxtı bitib, lütfən onu dəyişin + + Your password has expired. Please contact the administrator to change it + Şifrənizin vaxtı bitib. Onu dəyişmək üçün inzibatçıya müraciət edin + + + Terminal locked, please contact administrator + Terminal kilidləndi, lütfən inzibatçıya bildirin + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,6 +243,17 @@ Cancel İmtina + + The reason of inhibit. + Donmanın səbəbi + + + + LighterGreeter + + Standard Mode + Standart rejim + LockContent @@ -288,6 +333,14 @@ Switch system Başqa sistemə keçid + + Update and Shut Down + Yenilə və Söndür + + + Update and Reboot + Yenilə və Yenidən başlat + SystemMonitor @@ -296,6 +349,55 @@ Sistem İzləyicisini başlatmaq + + UdcpMFALoginWidget + + 发送验证码 + Doğrulama kodunu göndərin + + + 请输入手机号 + Lütfən telefon nömrəsini daxil edin + + + 请输入验证码 + Lütfən doğrulama kodunu daxil edin + + + 获取验证码 + Doğrulama kodunu əldə edin + + + + UpdateWorker + + Update + Yenilə + + + Please plug in and then install updates. + Elektrik şəbəkəsinə qoşun və yenilənmələri yenidən quraşdırın. + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Sistemdən çıxmaq istədiyinizə əminsiniz? + + Update and Shut Down + Yenilə və Söndür + + + Update and Reboot + Yenilə və Yenidən başlat + + + Closing the programs and shutting down, please wait... + Proqramlar bağlanır və söndürülür, lütfən gözləyin... + + + Closing the programs and rebooting, please wait... + Proqramlar bağlanır və yenidən başladılır, lütfən gözləyin... + + + Closing the programs and logging out, please wait... + Proqramlar bağlanır və sistemdən çıxılır, lütfən gözləyin... + + + + dss::module::AssistLoginWidget + + Automatic login + Birbaşa giriş + dss::module::NetworkModule diff --git a/translations/dde-session-shell_bg.ts b/translations/dde-session-shell_bg.ts index 543f288b..260998ab 100644 --- a/translations/dde-session-shell_bg.ts +++ b/translations/dde-session-shell_bg.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Изключване + Verify your fingerprint + - - - - - Reboot - Рестартиране + Verification successful + - - - - Suspend - Приспиване + + Verification failed, %n chances left + - - - Hibernate - Хибернация + Verification failed, only one chance left + - - - - Log out - Излизане + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - Наистина ли искате да изключите ? + Iris ID + - - Are you sure you want to reboot? - Наистина ли искате да рестартирате? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - Наистина ли искате да излезете? + Verification failed, only one chance left + - - Lock - 3аключване + Verify your Iris ID + - - Switch user - Cмяна на потребител + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Грешна парола - - The domain account or password is not correct. Please enter again. - Домейн регистрацията или паролата са неправилни. Моля въведете ги отново. + Password + Парола + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Грешна парола InhibitWarnView - Cancel Отказ + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - Домейн акаунт - - - Fingerprint verification timed out, please enter your password manually Времето за проверка на пръстовия отпечатък изтече, Моля, въведете Вашата парола ръчно - Failed to match fingerprint Грешка при съвпадение на пръстов отпечатък - - - Wrong Password - Грешна парола - MultiUsersWarningView - Cancel Отказ - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Горните потребители все още са влезли и данните им ще бъдат изгубени при спирането, да продължа ли с него? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Горните потребители все още са влезли и данните им ще бъдат изгубени при рестарта, да продължа ли с него? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Изключване - - Reboot Рестартиране - - Suspend Приспиване - - Hibernate Хибернация + + Lock + 3аключване + + + Log out + Излизане + + + Switch user + Cмяна на потребител + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Стартирай Наблюдение на системата - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password - Повторете паролата + Update + - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password - Моля, въведете новата парола + Please select the account for login + - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Парола + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Въведете Вашата парола, за да рестартирате + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down - Въведете Вашата парола, за да изключите + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Изключване + + + Reboot + Рестартиране + + + Suspend + Приспиване + + + Hibernate + Хибернация + + + Log out + Излизане + + + Are you sure you want to shut down? + Наистина ли искате да изключите ? + + + Are you sure you want to reboot? + Наистина ли искате да рестартирате? + + + Are you sure you want to log out? + Наистина ли искате да излезете? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_bn.ts b/translations/dde-session-shell_bn.ts index 49f89aa4..81ca32f2 100644 --- a/translations/dde-session-shell_bn.ts +++ b/translations/dde-session-shell_bn.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - বন্ধ করুন + Verify your fingerprint + - - - - - Reboot - পুনঃরায় চালু করুন + Verification successful + - - - - Suspend - সাময়িক ভাবে বন্ধ করুন + + Verification failed, %n chances left + - - - Hibernate - হায়বারনেট + Verification failed, only one chance left + - - - - Log out - লগ আউট করুন + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - আপনি কি নিশ্চিত যে, আপনি বন্ধ করতে চান? + Iris ID + - - Are you sure you want to reboot? - আপনি কি নিশ্চিত যে, আপনি পুনরায় চালু করতে চান? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - আপনি কি নিশ্চিত যে, আপনি লগ আউট করতে চান? + Verification failed, only one chance left + - - Lock - লক করুন + Verify your Iris ID + - - Switch user - ব্যবহারকারী পরিবর্তন করুন + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password - একটি আঙ্গুলের ছাপ অথবা পাসওয়ার্ড যাচাই করুন + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password ভুল পাসওয়ার্ড - - The domain account or password is not correct. Please enter again. - ডোমেন অ্যাকাউন্ট বা পাসওয়ার্ড সঠিক নয়। দয়া করে আবার প্রবেশ করান। + Password + পাসওয়ার্ড + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + ভুল পাসওয়ার্ড InhibitWarnView - Cancel বাতিল করুন + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - ডোমেন অ্যাকাউন্ট - - - Fingerprint verification timed out, please enter your password manually আঙুলের ছাপ যাচাই করার সময় শেষ, দয়া করে হাত দিয়ে পাসওয়ার্ড প্রবেশ করান। - Failed to match fingerprint আঙুলের ছাপ মিলাতে ব্যর্থ হয়েছে - - - Wrong Password - ভুল পাসওয়ার্ড - MultiUsersWarningView - Cancel বাতিল করুন - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? উপরে থাকা ব্যবহারকারীরা এখনও লগ ইন করে আছেন এবং বন্ধ হওয়ার কারণে ডেটা হারিয়ে যাবে, আপনি কি নিশ্চিত যে, আপনি বন্ধ করতে চান? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? উপরে থাকা ব্যবহারকারীরা এখনও লগ ইন করে আছেন এবং বন্ধ হওয়ার কারণে ডেটা হারিয়ে যাবে, আপনি কি নিশ্চিত যে আপনি পুনরায় চালু করতে চান? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down বন্ধ করুন - - Reboot পুনঃরায় চালু করুন - - Suspend সাময়িক ভাবে বন্ধ করুন - - Hibernate হায়বারনেট + + Lock + লক করুন + + + Log out + লগ আউট করুন + + + Switch user + ব্যবহারকারী পরিবর্তন করুন + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor সিস্টেম মনিটর চালু করুন - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password - পুনরায় পাসওয়ার্ড দিন + Update + - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - পাসওয়ার্ড + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - রিস্টার্ট করতে আপনার পাসওয়ার্ড প্রবেশ করান + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down - বন্ধ করতে আপনার পাসওয়ার্ড প্রবেশ করান + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + বন্ধ করুন + + + Reboot + পুনঃরায় চালু করুন + + + Suspend + সাময়িক ভাবে বন্ধ করুন + + + Hibernate + হায়বারনেট + + + Log out + লগ আউট করুন + + + Are you sure you want to shut down? + আপনি কি নিশ্চিত যে, আপনি বন্ধ করতে চান? + + + Are you sure you want to reboot? + আপনি কি নিশ্চিত যে, আপনি পুনরায় চালু করতে চান? + + + Are you sure you want to log out? + আপনি কি নিশ্চিত যে, আপনি লগ আউট করতে চান? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_bo.ts b/translations/dde-session-shell_bo.ts index 9982bb6b..7b5bf37a 100644 --- a/translations/dde-session-shell_bo.ts +++ b/translations/dde-session-shell_bo.ts @@ -27,7 +27,7 @@ Device unavailable! - + སྒྲིག་ཆས་སྤྱོད་མི་རུང་། @@ -80,6 +80,25 @@ མིག་འབྲས་IDསྒོ་ལྕགས་བརྒྱབ་ཟིན་པས། གསང་ཨང་ནང་འཇུག་བྱེད། + + AuthPasskey + + Please plug in the security key + བདེ་འཇགས་གསང་ལྡེ་འཇུག་རོགས། + + + Verification successful + ར་འཕྲོད་པ། + + + Verification failed + ར་སྤྲོད་བྱེད་མ་ཐུབ། + + + Identifying the security key + བདེ་འཇགས་གསང་ལྡེ་དབྱེ་འབྱེད་བྱེད་བཞིན་པ། + + AuthPassword @@ -191,6 +210,21 @@ Password expired, please change གསང་ཨང་དུས་ཚོད་ཡོལ་ཟིན་པས། བཟོ་བཅོས་བྱེད་རོགས། + + Your password has expired. Please contact the administrator to change it + ཁྱེད་ཀྱི་གསང་ཨང་དུས་ཚད་འཐིམས་པས་དོ་དམ་པ་དང་འབྲེལ་བ་བྱས་ནས་གསང་ཨང་བཟོ་བཅོས་བྱོས། + + + Terminal locked, please contact administrator + སྒྲིག་ཆས་འདི་བཀག་ཟིན་པས། དོ་དམ་པར་འབྲེལ་བ་གནང་རོགས། + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,6 +243,17 @@ Cancel འདོར་བ། + + The reason of inhibit. + The reason of inhibit. + + + + LighterGreeter + + Standard Mode + ཚད་ལྡན་དཔེ་རྣམ། + LockContent @@ -274,7 +319,7 @@ Lock - ཟྭ་རྒྱག + བརྙན་ཡོལ་སྒོ་ལྕགས་བརྒྱབ། Log out @@ -288,6 +333,14 @@ Switch system རྒྱུད་ཁོངས་བརྗེ་བ། + + Update and Shut Down + གསར་སྒྱུར་དང་སྦྲགས་སྒོ་རྒྱག་པ། + + + Update and Reboot + གསར་སྒྱུར་དང་སྦྲགས་བསྐྱར་དུ་འགོ་སློང་བ། + SystemMonitor @@ -296,6 +349,55 @@ རྒྱུད་ཁོངས་ཀྱི་ལྟ་ཆས་འགོ་སློང་། + + UdcpMFALoginWidget + + 发送验证码 + ར་སྤྲོད་ཨང་རྟགས་བསྐུར་རོགས། + + + 请输入手机号 + ཁ་པར་ཨང་གྲངས་འཇུག་རོགས། + + + 请输入验证码 + ར་སྤྲོད་ཨང་རྟགས་འཇུག་རོགས། + + + 获取验证码 + ར་སྤྲོད་ཨང་རྟགས་ལེན་པ། + + + + UpdateWorker + + Update + གསར་སྒྱུར། + + + Please plug in and then install updates. + གློག་ཁུངས་དང་གཏུགས་རྗེས་གསར་སྒྱུར་བྱེད་འགོ་རྩོམ། + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? ཁྱོད་ཀྱི་ཐོ་འདོར་རྒྱུ་གཏན་ཁེལ་ལམ། + + Update and Shut Down + གསར་སྒྱུར་དང་སྦྲགས་སྒོ་རྒྱག་པ། + + + Update and Reboot + གསར་སྒྱུར་དང་སྦྲགས་བསྐྱར་དུ་འགོ་སློང་བ། + + + Closing the programs and shutting down, please wait... + གོང་གི་བྱ་རིམ་ཁ་བརྒྱབ་ནས་གློ་སྒོ་བརྒྱབ་བཞིན་ཡོད་པས། ཏོག་ཙམ་སྒུག་རོགས། + + + Closing the programs and rebooting, please wait... + གོང་གི་བྱ་རིམ་ཁ་བརྒྱབ་ནས་བསྐྱར་སློང་བྱ་བཞིན་ཡོད་པས། ཏོག་ཙམ་སྒུག་རོགས། + + + Closing the programs and logging out, please wait... + གོང་གི་བྱ་རིམ་ཁ་བརྒྱབ་ནས་རྩིས་ཐོ་བསུབ་བཞིན་ཡོད་པས། ཏོག་ཙམ་སྒུག་རོགས། + + + + dss::module::AssistLoginWidget + + Automatic login + + dss::module::NetworkModule diff --git a/translations/dde-session-shell_bqi.ts b/translations/dde-session-shell_bqi.ts new file mode 100644 index 00000000..f3178792 --- /dev/null +++ b/translations/dde-session-shell_bqi.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_br.ts b/translations/dde-session-shell_br.ts new file mode 100644 index 00000000..4c59a090 --- /dev/null +++ b/translations/dde-session-shell_br.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Ger-tremen + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + Nullañ + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + Nullañ + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ca.ts b/translations/dde-session-shell_ca.ts index 0fac14ed..59d0e953 100644 --- a/translations/dde-session-shell_ca.ts +++ b/translations/dde-session-shell_ca.ts @@ -27,7 +27,7 @@ Device unavailable! - + Dispositiu no disponible! @@ -80,6 +80,25 @@ Identificació d'iris blocada. Useu la contrasenya. + + AuthPasskey + + Please plug in the security key + Si us plau, connecteu la clau de seguretat. + + + Verification successful + Verificació correcta + + + Verification failed + Ha fallat la verificació. + + + Identifying the security key + S'identifica la clau de seguretat + + AuthPassword @@ -191,6 +210,21 @@ Password expired, please change La contrasenya ha caducat. Si us plau, canvieu-la. + + Your password has expired. Please contact the administrator to change it + La contrasenya ha vençut. Poseu-vos en contacte amb l'administrador per canviar-la. + + + Terminal locked, please contact administrator + Terminal blocat, poseu-vos en contacte amb l'administrador. + + + + DeepinAuthFramework + + Wrong Password + Contrasenya incorrecta + GreeterWorker @@ -209,12 +243,23 @@ Cancel Cancel·la + + The reason of inhibit. + El motiu de la inhibició + + + + LighterGreeter + + Standard Mode + Mode estàndard + LockContent Lock Screen - Pantalla de bloqueig + Pantalla de blocatge Failed to lock screen @@ -262,11 +307,11 @@ Reboot - Reinicia + Reinicia't Suspend - Suspèn + Suspèn-te Hibernate @@ -288,6 +333,14 @@ Switch system Canvia de sistema + + Update and Shut Down + Actualitza i atura't + + + Update and Reboot + Actualitza i reinicia't + SystemMonitor @@ -296,6 +349,55 @@ Inicia el monitor del sistema + + UdcpMFALoginWidget + + 发送验证码 + Envieu el codi de verificació + + + 请输入手机号 + Introduïu el número de telèfon + + + 请输入验证码 + Introduïu el codi de verificació + + + 获取验证码 + obtenir el codi de verificació + + + + UpdateWorker + + Update + Actualitza + + + Please plug in and then install updates. + Si us plau, endolleu l'ordinador i després instal·leu les actualitzacions. + + + + UsersWithTheSameName + + Return + Retorn + + + Please select the account for login + Si us plau, seleccioneu el compte per entrar-hi. + + + Local Account + Compte local + + + Domain Account + Compte del domini + + WarningContent @@ -328,11 +430,11 @@ Reboot - Reinicia + Reinicia't Suspend - Suspèn + Suspèn-te Hibernate @@ -354,6 +456,33 @@ Are you sure you want to log out? Segur que voleu sortir de la sessió? + + Update and Shut Down + Actualitza i atura't + + + Update and Reboot + Actualitza i reinicia't + + + Closing the programs and shutting down, please wait... + Es tanquen els programes i s'atura. Espereu, si us plau... + + + Closing the programs and rebooting, please wait... + Es tanquen els programes i es reinicia. Espereu, si us plau... + + + Closing the programs and logging out, please wait... + Es tanquen els programes i se surt de la sessió. Espereu, si us plau... + + + + dss::module::AssistLoginWidget + + Automatic login + Entrada automàtica + dss::module::NetworkModule diff --git a/translations/dde-session-shell_cgg.ts b/translations/dde-session-shell_cgg.ts new file mode 100644 index 00000000..6bb604a7 --- /dev/null +++ b/translations/dde-session-shell_cgg.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_cs.ts b/translations/dde-session-shell_cs.ts index 3658f89f..ece4184b 100644 --- a/translations/dde-session-shell_cs.ts +++ b/translations/dde-session-shell_cs.ts @@ -11,7 +11,7 @@ Verification failed, %n chances left - Ověření se nezdařilo – zbývá %d pokusOvěření se nezdařilo – zbývají %n pokusyOvěření se nezdařilo – zbývá %d pokusůOvěření se nezdařilo – zbývá %d pokusů + Ověření se nezdařilo, zbývá %n pokusOvěření se nezdařilo, zbývají %n pokusyOvěření se nezdařilo, zbývá %n pokusůOvěření se nezdařilo, zbývají %n pokusy Verification failed, only one chance left @@ -27,7 +27,7 @@ Device unavailable! - + Zařízení není k dispozici! @@ -57,7 +57,7 @@ AuthIris Iris ID - Identifikace duhovkou + Identifikace oční duhovkou Verification successful @@ -65,7 +65,7 @@ Verification failed, %n chances left - Ověření se nezdařilo, zbývá %n pokusOvěření se nezdařilo, zbývají %n pokusyOvěření se nezdařilo, zbývá %n pokusůOvěření se nezdařilo, zbývají %n pokusy + Ověření se nezdařilo – zbývá %d pokusOvěření se nezdařilo – zbývají %n pokusyOvěření se nezdařilo – zbývá %d pokusůOvěření se nezdařilo – zbývají %n pokusy Verification failed, only one chance left @@ -80,6 +80,25 @@ Identifikace duhovkou uzamčena – použijte heslo + + AuthPasskey + + Please plug in the security key + Připojte bezpečnostní klíč + + + Verification successful + Úspěšně ověřeno + + + Verification failed + Ověření se nezdařilo + + + Identifying the security key + Bezpečnostní klíč je identifikován + + AuthPassword @@ -112,7 +131,7 @@ Reset Password - Vynulovat heslo + Nastavit heslo znovu Forgot password? @@ -131,7 +150,7 @@ Reset Password - Vynulovat heslo + Nastavit heslo znovu Forgot password? @@ -191,6 +210,21 @@ Password expired, please change Platnost hesla skončila – prosím změňte si ho + + Your password has expired. Please contact the administrator to change it + Platnost vašeho hesla vypršela. Kontaktujte prosím správce a změňte si ho. + + + Terminal locked, please contact administrator + Terminál uzamčen – obraťte se na správce + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,6 +243,17 @@ Cancel Zrušit + + The reason of inhibit. + Důvod inhibováni. + + + + LighterGreeter + + Standard Mode + Standardní režim + LockContent @@ -288,6 +333,14 @@ Switch system Přepnout systém + + Update and Shut Down + Aktualizovat a vypnout + + + Update and Reboot + Aktualizovat a restartovat + SystemMonitor @@ -296,6 +349,55 @@ Spustit Systémové prostředky + + UdcpMFALoginWidget + + 发送验证码 + CAPTCHA + + + 请输入手机号 + Zadejte prosím číslo svého mobilního telefonu + + + 请输入验证码 + Zadejte prosím ověřovací kód + + + 获取验证码 + Získat CAPTCHA + + + + UpdateWorker + + Update + Aktualizovat + + + Please plug in and then install updates. + Připojte se a nainstalujte aktualizace. + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -304,7 +406,7 @@ To close the program, click Cancel, and then close the program. - Pro zavření programu klikněte na Storno a potom program zavřete. + Pro zavření programu klikněte na Zrušit a potom program zavřete. The programs are preventing the computer from reboot, and forcing reboot may cause data loss. @@ -354,6 +456,33 @@ Are you sure you want to log out? Opravdu se chcete odhlásit? + + Update and Shut Down + Aktualizovat a vypnout + + + Update and Reboot + Aktualizovat a restartovat + + + Closing the programs and shutting down, please wait... + Zavírání aplikací a vypínání – vyčkejte… + + + Closing the programs and rebooting, please wait... + Zavírání aplikací a restartování – vyčkejte… + + + Closing the programs and logging out, please wait... + Zavírání aplikací a odhlašování – vyčkejte… + + + + dss::module::AssistLoginWidget + + Automatic login + Automatické přihlášení + dss::module::NetworkModule diff --git a/translations/dde-session-shell_da.ts b/translations/dde-session-shell_da.ts index fbac61be..963fc3bf 100644 --- a/translations/dde-session-shell_da.ts +++ b/translations/dde-session-shell_da.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Programmet forhindre computeren i at lukke ned og hvis den tvinges til at lukke ned kan det forårsage tab af data. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Luk programmet ved at klikke på Annuller og luk så programmet. + Verification successful + Bekræftelse lykkedes + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Programmet forhindre computeren i at genstarte og hvis den tvinges til at genstarte kan det forårsage tab af data. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Programmet forhindre computeren i at gå i dvale og hvis den tvinges til at gå i dvale kan det forårsage tab af data. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Programmet forhindre computeren i at gå i dvale og hvis den tvinges til at gå i dvale kan det forårsage tab af data. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Programmet forhindre computeren i at logge ud og hvis den tvinges til at logge ud kan det forårsage tab af data. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Luk ned + Verify your fingerprint + - - - - - Reboot - Genstart + Verification successful + Bekræftelse lykkedes + + + Verification failed, %n chances left + - - - Suspend - Hvile + Verification failed, only one chance left + - - - Hibernate - Dvale + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - Log ud + Iris ID + - - Are you sure you want to shut down? - Er du sikker på, at du vil lukke ned? + Verification successful + Bekræftelse lykkedes + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Er du sikker på, at du vil genstarte? + Verification failed, only one chance left + - - Are you sure you want to log out? - Er du sikker på, at du vil logge ud? + Verify your Iris ID + - - Lock - Lås + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Skift bruger + Please plug in the security key + - - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + Bekræftelse lykkedes + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Forkert adgangskode - - The account or password is not correct. Please enter again. + Password + Adgangskode + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + Nulstil Adgangskode + + + Forgot password? + Glemt adgangskode? + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + Nulstil Adgangskode + + + Forgot password? + Glemt adgangskode? + + + + AuthUKey + + Verification successful + Bekræftelse lykkedes + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Konto + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Adgangskoden er udløbet. Skift den venligst + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + Forkert adgangskode + InhibitWarnView - Cancel Annuller + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Lås skærm - Failed to lock screen Kunne ikke låse skærmen @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Bekræftelse af fingeraftryk fik timeout, indtast venligst din adgangskode manuelt - Failed to match fingerprint Kunne ikke matche fingeraftryk - - - Wrong Password - Forkert adgangskode - MultiUsersWarningView - Cancel Annuller - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Brugerne ovenfor er stadigvæk logget ind og data vil gå tabt pga. nedlukning. Er du sikker på, at du vil lukke ned? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Brugerne ovenfor er stadigvæk logget ind og data vil gå tabt pga. genstart. Er du sikker på, at du vil genstarte? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Luk ned - - Reboot Genstart - - Suspend Hvile - - Hibernate Dvale + + Lock + Lås + + + Log out + Log ud + + + Switch user + Skift bruger + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Start systemovervågning - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Adgangskoden er udløbet. Skift den venligst + 发送验证码 + - - New password - Ny adgangskode + 请输入手机号 + - - Repeat password - Gentag adgangskode + 请输入验证码 + - - Failed to change your password - Kunne ikke ændre din adgangskode + 获取验证码 + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak - Adgangskoden er for svag + Return + - - Please enter the new password - Indtast venligst den nye adgangskode + Please select the account for login + - - Please repeat the new password - Gentag venligst den nye adgangskode + Local Account + - - Passwords do not match - Adgangskoderne er ikke ens + Domain Account + - UserLoginWidget + WarningContent - - Password - Adgangskode + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Programmet forhindre computeren i at lukke ned og hvis den tvinges til at lukke ned kan det forårsage tab af data. - - Account - Konto + To close the program, click Cancel, and then close the program. + Luk programmet ved at klikke på Annuller og luk så programmet. - - Please enter the account - Indtast venligst kontoen + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Programmet forhindre computeren i at genstarte og hvis den tvinges til at genstarte kan det forårsage tab af data. - - Please enter the password - Indtast venligst adgangskoden + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Programmet forhindre computeren i at gå i dvale og hvis den tvinges til at gå i dvale kan det forårsage tab af data. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Programmet forhindre computeren i at gå i dvale og hvis den tvinges til at gå i dvale kan det forårsage tab af data. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Programmet forhindre computeren i at logge ud og hvis den tvinges til at logge ud kan det forårsage tab af data. + + + Shut down + Luk ned + + + Reboot + Genstart + + + Suspend + Hvile + + + Hibernate + Dvale + + + Log out + Log ud + + + Are you sure you want to shut down? + Er du sikker på, at du vil lukke ned? + + + Are you sure you want to reboot? + Er du sikker på, at du vil genstarte? + + + Are you sure you want to log out? + Er du sikker på, at du vil logge ud? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Tænd + + + Turn off + Sluk \ No newline at end of file diff --git a/translations/dde-session-shell_de.ts b/translations/dde-session-shell_de.ts index 5d5b93f3..219cdffa 100644 --- a/translations/dde-session-shell_de.ts +++ b/translations/dde-session-shell_de.ts @@ -11,7 +11,7 @@ Verification failed, %n chances left - + Verifizierung fehlgeschlagen, nur noch %n Chancen übrig Verification failed, only one chance left @@ -27,7 +27,7 @@ Device unavailable! - + Gerät nicht verfügbar! @@ -42,7 +42,7 @@ Verification failed, %n chances left - + Verifizierung fehlgeschlagen, nur noch %n Chance übrigVerifizierung fehlgeschlagen, nur noch %n Chancen übrig Verification failed, only one chance left @@ -65,7 +65,7 @@ Verification failed, %n chances left - + Verifizierung fehlgeschlagen, nur noch %n Chance übrigVerifizierung fehlgeschlagen, nur noch %n Chancen übrig Verification failed, only one chance left @@ -80,6 +80,25 @@ + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + AuthPassword @@ -108,7 +127,7 @@ Please try again %n minutes later - Bitte versuchen Sie es %n Minute später erneutBitte versuchen Sie es %n Minuten später erneut + Bitte versuchen Sie es 1 Minute später erneutBitte versuchen Sie es %n Minuten später erneut Reset Password @@ -174,7 +193,7 @@ Please try again %n minutes later - Bitte versuchen Sie es %n Minute später erneutBitte versuchen Sie es %n Minuten später erneut + Bitte versuchen Sie es 1 Minute später erneutBitte versuchen Sie es %n Minuten später erneut @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - Ihr Passwort läuft in %d Tage ab, bitte ändern Sie es rechtzeitigIhr Passwort läuft in %d Tagen ab, bitte ändern Sie es rechtzeitig + Password expired, please change Passwort abgelaufen, bitte ändern + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,6 +243,17 @@ Cancel Abbrechen + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + Standardmodus + LockContent @@ -288,6 +333,14 @@ Switch system System wechseln + + Update and Shut Down + Aktualisieren und herunterfahren + + + Update and Reboot + Aktualisieren und neu starten + SystemMonitor @@ -296,6 +349,55 @@ Systemmonitor starten + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Sind Sie sicher, dass Sie sich abmelden möchten? + + Update and Shut Down + Aktualisieren und herunterfahren + + + Update and Reboot + Aktualisieren und neu starten + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + Automatische Anmeldung + dss::module::NetworkModule diff --git a/translations/dde-session-shell_de_CH.ts b/translations/dde-session-shell_de_CH.ts new file mode 100644 index 00000000..d3187d22 --- /dev/null +++ b/translations/dde-session-shell_de_CH.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_de_DE.ts b/translations/dde-session-shell_de_DE.ts new file mode 100644 index 00000000..30678014 --- /dev/null +++ b/translations/dde-session-shell_de_DE.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + Face ID + + + Verification successful + Verifikation erfolgreich + + + Verification failed, %n chances left + Verifikation fehlgeschlagen, nur noch ein Versuch übrigVerifikation fehlgeschlagen, noch %1 Versuche + + + Verification failed, only one chance left + Verifizierung felgeschlagen, nurmehr ein Versuch möglich + + + Verify your Face ID + Face-ID verifizieren + + + Face ID locked, use password please + Face-ID gesperrt, bitte Passwort benützen + + + Device unavailable! + Gerät nicht verfübar! + + + + AuthFingerprint + + Verify your fingerprint + Ihren Fingerabdruck verifizieren + + + Verification successful + Verifizierung erfolgreich + + + Verification failed, %n chances left + Verifikation fehlgeschlagen, nur noch ein Versuch möglichVerifizierung fehlgeschlagen, noch %n Versuche + + + Verification failed, only one chance left + Verifizierung fehlgeschlagen, nur noch ein Versuch möglich + + + Fingerprint locked, use password please + Fingerabdruck gesperrt, bitte Passwort benutzen + + + + AuthIris + + Iris ID + Iris-ID + + + Verification successful + Verifizierung erfolgreich + + + Verification failed, %n chances left + Verifizierung fehlgeschlagen, noch %n Versuche übrigVerifizierung fehlgeschlagen, noch %n Versuche + + + Verification failed, only one chance left + Verifizierung fehlgeschlagen, nur noch ein Versuch möglich + + + Verify your Iris ID + Iris-ID verifizieren + + + Iris ID locked, use password please + Iris-ID gesperrt, bitte Passwort benützen + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + Verifizierung erfolgreich + + + Verification failed, %n chances left + Verifizierung fehlgeschlagen, noch %n Versuche übrigVerifizierung fehlgeschlagen, noch %1 Versuche übrig + + + Verification failed, only one chance left + Verifikation fehlgeschlagen, nur noch ein Versuch möglich + + + Wrong Password + Falsches Passwort + + + Password + Passwort + + + Please try again 1 minute later + Bitte in 1 Minute nochmals versuchen + + + Please try again %n minutes later + Bitte in %1 Minuten nochmals versuchenBitte in %n Minuten nochmals versuchen + + + Reset Password + Passwort zurücksetzen + + + Forgot password? + Passwort vergessen? + + + + AuthSingle + + Please try again 1 minute later + Bitte in 1 Minute nochmals versuchen + + + Please try again %n minutes later + Bitte in %1 Minuten nochmals versuchenBitte in %n Minuten nochmals versuchen + + + Reset Password + Passwort zurücksetzen + + + Forgot password? + Passwort vergessen? + + + + AuthUKey + + Verification successful + Verifizierung erfolgreich + + + Verification failed, %n chances left + Verifizierung fehlgeschlagen, noch %1 Versuche übrigVerifizierung fehlgeschlagen, noch %1 Versuche + + + Verification failed, only one chance left + Verifizierung fehlgeschlagen, nur noch ein Versuch möglich + + + Wrong PIN + Falsche PIN + + + UKey is required + UKey wird benötigt + + + Enter your PIN + PIN eingeben + + + Please try again %n minute(s) later + Bitte in %1 Minute(n) nochmals versuchenBitte in %n Minute(n) nochmals versuchen + + + Please try again 1 minute later + Bitte in 1 Minute nochmals versuchen + + + Please try again %n minutes later + Bitte in %1 Minuten nochmals versuchenBitte in %n Minuten nochmals versuchen + + + + AuthWidget + + Account + Konto + + + Your password will expire in %n days, please change it timely + Ihr Passwort wird in %n Tagen abgelaufen sein, bitte zeitig erneuernIhr Passwort wird in %n Tagen ablaufen, bitte zeitig erneuern + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + Falsches Konto + + + Wrong Password + Falsches Passwort + + + + InhibitWarnView + + Cancel + Abbrechen + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + Bildschirm sperren + + + Failed to lock screen + Bildschirm sperren fehlgeschlagen + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + Fingerabdruck-Verifizierung abgelaufen, bitte tippen Sie ihr Passwort ein + + + Failed to match fingerprint + Fingerabdrücke stimmen nicht überein + + + + MultiUsersWarningView + + Cancel + Abbrechen + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + Die obigen Benutzer sind noch angemeldet und Daten würden beim Herunterfahren verloren gehen, sind Sie sicher, dass Sie herunterfahren möchten? + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + Die obigen Benutzer sind noch angemeldet und Daten würden beim erneuten Hochfahren verloren gehen, sind Sie sicher, dass Sie herunterfahren möchten? + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + Herunterfahren + + + Reboot + Neu Booten + + + Suspend + Bereitschaft + + + Hibernate + Ruhezustand + + + Lock + Sperren + + + Log out + Abmelden + + + Switch user + Benutzer wechseln + + + Switch system + System wechseln + + + Update and Shut Down + Aktualisieren und herunterfahren + + + Update and Reboot + Aktualisieren und neustarten + + + + SystemMonitor + + Start system monitor + System-Monitor starten + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + Aktualisieren + + + Please plug in and then install updates. + Bitte ans Stromnetz anschließen und dann Aktualisierungen installieren + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Die Programme verhindern ein Herunterfahren des Computers, und ein Erzwingen kann Datenverlust bedeuten. + + + To close the program, click Cancel, and then close the program. + Um das Programm zu beenden, klicken Sie auf Abbrechen und beenden dann das Programm. + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + DIe Programme verhindern das erneute Hochfahren des Computers, ein Erzwingen kann Datenverlust bedeuten + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + DIe Programme verhindern das Abschalten des Computers, ein Erzwingen kann Datenverlust bedeuten. + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + DIe Programme verhindern den Ruhezustand des Computers, ein Erzwingen kann Datenverlust bedeuten + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + DIe Programme verhindern das Abmelden des Computers, ein Erzwingen kann Datenverlust bedeuten + + + Shut down + Herunterfahren + + + Reboot + Neu Hochfahren + + + Suspend + Bereitschaft + + + Hibernate + Ruhezustand + + + Log out + Abmelden + + + Are you sure you want to shut down? + Sind Sie sicher, dass Sie sie herunterfahren möchten? + + + Are you sure you want to reboot? + Sind Sie sicher, dass Sie sie neu hochfahren möchten? + + + Are you sure you want to log out? + Sind Sie sicher, dass Sie sie sich abmelden möchten? + + + Update and Shut Down + Aktualisieren und herunterfahren + + + Update and Reboot + Aktualisieren und neustarten + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Anschalten + + + Turn off + Abschalten + + + \ No newline at end of file diff --git a/translations/dde-session-shell_el.ts b/translations/dde-session-shell_el.ts index 61acc1eb..65de76ba 100644 --- a/translations/dde-session-shell_el.ts +++ b/translations/dde-session-shell_el.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. - Για κλείσιμο του προγράμματος, Πάτα Άκυρο και μετά κλείσε το πρόγραμμα. + Verification successful + Επιτυχής επαλήθευση + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - + Verification failed, only one chance left + Επαλήθευση απέτυχε, απέμεινε μόνο μία προσπάθεια - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Τερματισμός λειτουργίας + Verify your fingerprint + Επαλήθευση του δακτυλικού αποτυπώματος σας - - - - - Reboot - Επανεκκίνηση + Verification successful + Επιτυχής επαλήθευση + + + Verification failed, %n chances left + - - - Suspend - Αναστολή + Verification failed, only one chance left + Επαλήθευση απέτυχε, απέμεινε μόνο μία προσπάθεια - - - Hibernate - Αδρανοποίηση + Fingerprint locked, use password please + Το δαχτυλικό αποτύπωμα κλειδώθηκε, παρακαλώ χρησημοποιήστε κωδικό πρόσβασης + + + AuthIris - - - - Log out - Αποσύνδεση + Iris ID + - - Are you sure you want to shut down? - Σίγουρα θέλετε να πραγματοποιήσετε απενεργοποίηση; + Verification successful + Επιτυχής επαλήθευση + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Σίγουρα θέλετε επανεκίνηση; + Verification failed, only one chance left + Επαλήθευση απέτυχε, απέμεινε μόνο μία προσπάθεια - - Are you sure you want to log out? - Σίγουρα θέλετε αποσύνδεση; + Verify your Iris ID + - - Lock - Κλείδωμα + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Εναλλαγή χρήστη + Please plug in the security key + - - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + Επιτυχής επαλήθευση + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + Επαλήθευση απέτυχε, απέμεινε μόνο μία προσπάθεια + - Wrong Password Λάθος Κωδικός Πρόσβασης - - The account or password is not correct. Please enter again. - Λάθος λογαριασμός ή κωδικός πρόσβασης. Εισάγετε ξανά! + Password + Κωδικός πρόσβασης + + + Please try again 1 minute later + Παρακαλώ προσθήστε ξανά σε 1 λεπτό + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + Παρακαλώ προσθήστε ξανά σε 1 λεπτό + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + Επιτυχής επαλήθευση + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + Επαλήθευση απέτυχε, απέμεινε μόνο μία προσπάθεια + + + Wrong PIN + Λάθος PIN + + + UKey is required + Απαιτείται UKeyh + + + Enter your PIN + Εισάγετε το PIN σας + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + Παρακαλώ προσθήστε ξανά σε 1 λεπτό + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Λογαριασμός + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Ο κωδικός πρόσβασης έληξε, παρακαλώ αλλάξτε τον + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + Λάθος λογαριασμός + + + Wrong Password + Λάθος Κωδικός Πρόσβασης InhibitWarnView - Cancel Ακύρωση + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Κλείδωμα Οθόνης - Failed to lock screen Αποτυχία κλειδώματος οθόνης @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Τέλος χρόνου επαλήθευσης δακτυλικού αποτυπώματος, παρακαλώ εισάγετε τον κωδικό πρόσβασης χειροκίνητα - Failed to match fingerprint Αποτυχία αντιστοίχισης δακτυλικού αποτυπώματος - - - Wrong Password - Λάθος Κωδικός Πρόσβασης - MultiUsersWarningView - Cancel Ακύρωση - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Οι παραπάνω χρήστες εξακολουθούν να είναι συνδεδεμένοι και τα δεδομένα θα χαθούν λόγω τερματισμού λειτουργίας, είστε βέβαιοι ότι θέλετε να τερματίσετε τη λειτουργία; - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Οι παραπάνω χρήστες εξακολουθούν να είναι συνδεδεμένοι και τα δεδομένα θα χαθούν λόγω επανεκκίνησης, είστε βέβαιοι ότι θέλετε να επανεκκινήσετε; + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Τερματισμός λειτουργίας - - Reboot Επανεκκίνηση - - Suspend Αναστολή - - Hibernate Αδρανοποίηση + + Lock + Κλείδωμα + + + Log out + Έξοδος χρήστη + + + Switch user + Εναλλαγή χρήστη + + + Switch system + Εναλλαγή συστήματος + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Εκκίνηση παρακολούθησης συστήματος - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Ο κωδικός πρόσβασης έληξε, παρακαλούμε αλλάξτε τον + 发送验证码 + - - New password - Νέος κωδικός πρόσβασης + 请输入手机号 + - - Repeat password - Επανάλληψη κωδικού πρόσβασης + 请输入验证码 + - - Failed to change your password - Αποτυχία αλλαγής του κωδικού πρόσβασής σου + 获取验证码 + + + + UpdateWorker - - Password too weak - Κωδικός πολύ αδύναμος + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + - - Please enter the new password - Παρακαλούμε εισάγετε το νέο κωδικό πρόσβασης + Please select the account for login + - - Please repeat the new password - Παρακαλούμε επαναλάβετε τον νέο κωδικό + Local Account + - - Passwords do not match - Οι κωδικοί δεν ταιριάζουν + Domain Account + - UserLoginWidget + WarningContent - - Password - Κωδικός πρόσβασης + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Τα προγράμματα εμποδίζουν τον υπολογιστή από το να απενεργοποιηθεί, και η εξαναγκασμένη απενεργοποίηση μπορεί να προκαλέσει απώλεια δεδομένων. - - Account - Λογαριασμός + To close the program, click Cancel, and then close the program. + Για κλείσιμο του προγράμματος, πατήστε Άκυρο, και μετά κλείστε το πρόγραμμα. - - Please enter the account - Παρακαλούμε εισάγετε τον λογαριασμό + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Τα προγράμματα εμποδίζουν τον υπολογιστή από το να επανεκκινηθεί, και η εξαναγκασμένη επανεκκίνηση μπορεί να προκαλέσει απώλεια δεδομένων. - - Please enter the password - Παρακαλούμε εισάγετε τον κωδικό πρόσβασης + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Τα προγράμματα εμποδίζουν τον υπολογιστή από το να τεθεί σε αναστολή λειτουργίας, και η εξαναγκασμένη αναστολή λειτουργίας μπορεί να προκαλέσει απώλεια δεδομένων. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Τα προγράμματα εμποδίζουν τον υπολογιστή από το να αδρανοποιηθεί, και η εξαναγκασμένη αδρανοποίηση μπορεί να προκαλέσει απώλεια δεδομένων. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Τα προγράμματα εμποδίζουν την έξοδο χρήστη από τον υπολογιστή, και η εξαναγκασμένη έξοδος μπορεί να προκαλέσει απώλεια δεδομένων. + + + Shut down + Τερματισμός λειτουργίας + + + Reboot + Επανεκκίνηση + + + Suspend + Αναστολή λειτουργίας + + + Hibernate + Αδρανοποίηση + + + Log out + Έξοδος χρήστη + + + Are you sure you want to shut down? + Σίγουρα θέλετε να γίνει απενεργοποίηση; + + + Are you sure you want to reboot? + Σίγουρα θέλετε να γίνει επανεκκίνηση; + + + Are you sure you want to log out? + Σίγουρα θέλετε να γίνει έξοδος χρήστη; + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Ενεργοποίηση + + + Turn off + Απενεργοποίηση \ No newline at end of file diff --git a/translations/dde-session-shell_el_GR.ts b/translations/dde-session-shell_el_GR.ts new file mode 100644 index 00000000..7c3cb8ee --- /dev/null +++ b/translations/dde-session-shell_el_GR.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + Ακύρωση + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + Ακύρωση + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + Τερματισμός λειτουργίας + + + Reboot + + + + Suspend + Αναστολή λειτουργίας + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_en.ts b/translations/dde-session-shell_en.ts index 91b7e394..4753bd43 100644 --- a/translations/dde-session-shell_en.ts +++ b/translations/dde-session-shell_en.ts @@ -32,7 +32,7 @@ Device unavailable! - + Device unavailable! @@ -91,6 +91,25 @@ Iris ID locked, use password please + + AuthPasskey + + Please plug in the security key + + + + Verification successful + Verification successful + + + Verification failed + + + + Identifying the security key + + + AuthPassword @@ -223,16 +242,31 @@ Password expired, please change Password expired, please change + + Your password has expired. Please contact the administrator to change it + Your password has expired. Please contact the administrator to change it + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + Wrong Password + GreeterWorker Wrong account - Wrong account + Wrong account Wrong Password - Wrong Password + Wrong Password @@ -241,6 +275,17 @@ Cancel Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent @@ -320,6 +365,14 @@ Switch system Switch system + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor @@ -328,6 +381,55 @@ Start system monitor + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -386,6 +488,33 @@ Are you sure you want to log out? Are you sure you want to log out? + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + dss::module::NetworkModule diff --git a/translations/dde-session-shell_en_AU.ts b/translations/dde-session-shell_en_AU.ts index 3b0af364..6b58d979 100644 --- a/translations/dde-session-shell_en_AU.ts +++ b/translations/dde-session-shell_en_AU.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - To close the program, click Cancel, and then close the program. + Verification successful + Verification successful + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Shut down + Verify your fingerprint + - - - - - Reboot - Reboot + Verification successful + Verification successful + + + Verification failed, %n chances left + - - - Suspend - Suspend + Verification failed, only one chance left + - - - Hibernate - Hibernate + Fingerprint locked, use password please + Fingerprint locked, use password please + + + AuthIris - - - - Log out - Log out + Iris ID + - - Are you sure you want to shut down? - Are you sure you want to shut down? + Verification successful + Verification successful + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Are you sure you want to reboot? + Verification failed, only one chance left + - - Are you sure you want to log out? - Are you sure you want to log out? + Verify your Iris ID + - - Lock - Lock + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Switch user + Please plug in the security key + - - Switch system - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + Verification successful + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Wrong Password - - The account or password is not correct. Please enter again. - The account or password is not correct. Please enter again. + Password + Password + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + Verification successful + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Account + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Password expired, please change + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Wrong Password InhibitWarnView - Cancel Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Lock Screen - Failed to lock screen Failed to lock screen @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint Failed to match fingerprint - - - Wrong Password - Wrong Password - MultiUsersWarningView - Cancel Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Shut down - - Reboot Reboot - - Suspend Suspend - - Hibernate Hibernate + + Lock + Lock + + + Log out + Log out + + + Switch user + Switch user + + + Switch system + Switch system + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + - - New password - New password + 获取验证码 + + + + UpdateWorker - - Repeat password - Repeat password + Update + - - Failed to change your password - Failed to change your password + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - Password too weak + Return + - - Please enter the new password - Please enter the new password + Please select the account for login + - - Please repeat the new password - Please repeat the new password + Local Account + - - Passwords do not match - Passwords do not match + Domain Account + - UserLoginWidget + WarningContent - - Password - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account - Account + To close the program, click Cancel, and then close the program. + To close the program, click Cancel, and then close the program. - - Please enter the account - Please enter the account + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Please enter the password - Please enter the password + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + Shut down + Shut down + + + Reboot + Reboot + + + Suspend + Suspend + + + Hibernate + Hibernate + + + Log out + Log out + + + Are you sure you want to shut down? + Are you sure you want to shut down? + + + Are you sure you want to reboot? + Are you sure you want to reboot? + + + Are you sure you want to log out? + Are you sure you want to log out? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Turn on + + + Turn off + Turn off \ No newline at end of file diff --git a/translations/dde-session-shell_en_GB.ts b/translations/dde-session-shell_en_GB.ts index 2a863a60..bbbd03bb 100644 --- a/translations/dde-session-shell_en_GB.ts +++ b/translations/dde-session-shell_en_GB.ts @@ -1,297 +1,498 @@ - - - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - + Verification successful + + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Shut down + Verify your fingerprint + - - - - - Reboot - Reboot + Verification successful + + + + Verification failed, %n chances left + - - - Suspend - + Verification failed, only one chance left + - - - Hibernate - + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - + Iris ID + - - Are you sure you want to shut down? - + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - + Verification failed, only one chance left + - - Are you sure you want to log out? - + Verify your Iris ID + - - Lock - + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Password + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + - - Verify your fingerprint or password - + Terminal locked, please contact administrator + - GreeterWorkek + DeepinAuthFramework - Wrong Password - + + + + GreeterWorker - - The account or password is not correct. Please enter again. - + Wrong account + + + + Wrong Password + InhibitWarnView - Cancel Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - + - Failed to lock screen - + LockWorker - Fingerprint verification timed out, please enter your password manually - + - Failed to match fingerprint - - - - - Wrong Password - + MultiUsersWarningView - Cancel Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - + - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + ShutdownWidget - Shut down Shut down - - Reboot Reboot - - Suspend - + - - Hibernate - + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + SystemMonitor - Start system monitor - + - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - + 发送验证码 + - - New password - + 请输入手机号 + - - Repeat password - Repeat password + 请输入验证码 + - - Failed to change your password - + 获取验证码 + + + + UpdateWorker - - Password too weak - + Update + - - Please enter the new password - + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + - - Please repeat the new password - + Local Account + - - Passwords do not match - + Domain Account + - UserLoginWidget + WarningContent - - Password - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account - + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to reboot - + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Enter your password to shut down - + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + - - Please enter the account - + The programs are preventing the computer from log out, and forcing log out may cause data loss. + - - Please enter the password - + Shut down + Shut down - - - Please try again %n minute(s) later - - - - + + Reboot + Reboot + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + - + \ No newline at end of file diff --git a/translations/dde-session-shell_en_NO.ts b/translations/dde-session-shell_en_NO.ts new file mode 100644 index 00000000..a46d684a --- /dev/null +++ b/translations/dde-session-shell_en_NO.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_en_US.ts b/translations/dde-session-shell_en_US.ts new file mode 100644 index 00000000..c2cbb48c --- /dev/null +++ b/translations/dde-session-shell_en_US.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + Face ID + + + Verification successful + Verification successful + + + Verification failed, %n chances left + Verification failed, %n chances leftVerification failed, %n chances left + + + Verification failed, only one chance left + Verification failed, only one chance left + + + Verify your Face ID + Verify your Face ID + + + Face ID locked, use password please + Face ID locked, use password please + + + Device unavailable! + Device unavailable! + + + + AuthFingerprint + + Verify your fingerprint + Verify your fingerprint + + + Verification successful + Verification successful + + + Verification failed, %n chances left + Verification failed, %n chances leftVerification failed, %n chances left + + + Verification failed, only one chance left + Verification failed, only one chance left + + + Fingerprint locked, use password please + Fingerprint locked, use password please + + + + AuthIris + + Iris ID + Iris ID + + + Verification successful + Verification successful + + + Verification failed, %n chances left + Verification failed, %n chances leftVerification failed, %n chances left + + + Verification failed, only one chance left + Verification failed, only one chance left + + + Verify your Iris ID + Verify your Iris ID + + + Iris ID locked, use password please + Iris ID locked, use password please + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + Verification successful + + + Verification failed, %n chances left + Verification failed, %n chances leftVerification failed, %n chances left + + + Verification failed, only one chance left + Verification failed, only one chance left + + + Wrong Password + Wrong Password + + + Password + Password + + + Please try again 1 minute later + Please try again 1 minute later + + + Please try again %n minutes later + Please try again %n minutes laterPlease try again %n minutes later + + + Reset Password + Reset Password + + + Forgot password? + Forgot password? + + + + AuthSingle + + Please try again 1 minute later + Please try again 1 minute later + + + Please try again %n minutes later + Please try again %n minutes laterPlease try again %n minutes later + + + Reset Password + Reset Password + + + Forgot password? + Forgot password? + + + + AuthUKey + + Verification successful + Verification successful + + + Verification failed, %n chances left + Verification failed, %n chances leftVerification failed, %n chances left + + + Verification failed, only one chance left + Verification failed, only one chance left + + + Wrong PIN + Wrong PIN + + + UKey is required + UKey is required + + + Enter your PIN + Enter your PIN + + + Please try again %n minute(s) later + Please try again %n minute(s) laterPlease try again %n minute(s) later + + + Please try again 1 minute later + Please try again 1 minute later + + + Please try again %n minutes later + Please try again %n minutes laterPlease try again %n minutes later + + + + AuthWidget + + Account + Account + + + Your password will expire in %n days, please change it timely + Your password will expire in %n days, please change it timelyYour password will expire in %n days, please change it timely + + + Password expired, please change + Password expired, please change + + + Your password has expired. Please contact the administrator to change it + Your password has expired. Please contact the administrator to change it + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + Wrong account + + + Wrong Password + Wrong Password + + + + InhibitWarnView + + Cancel + Cancel + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + Standard Mode + + + + LockContent + + Lock Screen + Lock Screen + + + Failed to lock screen + Failed to lock screen + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + Fingerprint verification timed out, please enter your password manually + + + Failed to match fingerprint + Failed to match fingerprint + + + + MultiUsersWarningView + + Cancel + Cancel + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + ShutdownWidget + + Shut down + Shut down + + + Reboot + Reboot + + + Suspend + Suspend + + + Hibernate + Hibernate + + + Lock + Lock + + + Log out + Log out + + + Switch user + Switch user + + + Switch system + Switch system + + + Update and Shut Down + Update and Shut Down + + + Update and Reboot + Update and Reboot + + + + SystemMonitor + + Start system monitor + Start system monitor + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + Update + + + Please plug in and then install updates. + Please plug in and then install updates. + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + To close the program, click Cancel, and then close the program. + To close the program, click Cancel, and then close the program. + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + Shut down + Shut down + + + Reboot + Reboot + + + Suspend + Suspend + + + Hibernate + Hibernate + + + Log out + Log out + + + Are you sure you want to shut down? + Are you sure you want to shut down? + + + Are you sure you want to reboot? + Are you sure you want to reboot? + + + Are you sure you want to log out? + Are you sure you want to log out? + + + Update and Shut Down + Update and Shut Down + + + Update and Reboot + Update and Reboot + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Turn on + + + Turn off + Turn off + + + \ No newline at end of file diff --git a/translations/dde-session-shell_eo.ts b/translations/dde-session-shell_eo.ts index 46c71338..af13d963 100644 --- a/translations/dde-session-shell_eo.ts +++ b/translations/dde-session-shell_eo.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Elŝaltiti + Verify your fingerprint + - - - - - Reboot - Restartigi + Verification successful + - - - - Suspend - Paŭzigi + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out - Elsaluti + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - Bloki + Verify your Iris ID + - - Switch user - Ŝanĝi uzanton + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + - - Verify your fingerprint or password + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Erara pasvorto - - The domain account or password is not correct. Please enter again. + Password + Pasvorto + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Erara pasvorto + + InhibitWarnView - Cancel Nuligi + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint Ŝanĝi fingronprinton malsukcesis - - - Wrong Password - Erara pasvorto - MultiUsersWarningView - Cancel Nuligi - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Elŝaltiti - - Reboot Restartigi - - Suspend Paŭzigi - - Hibernate + + Lock + Bloki + + + Log out + Elsaluti + + + Switch user + Ŝanĝi uzanton + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Komencu sistemon-monitoro - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - Ripetu pasvorton + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password + Please plug in and then install updates. + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match + Please select the account for login + + + + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - Pasvorto + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Entajpi vian pasvorton por restartigi + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Elŝaltiti + + + Reboot + Restartigi + + + Suspend + Paŭzigi + + + Hibernate + + + + Log out + Elsaluti + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_es.ts b/translations/dde-session-shell_es.ts index 3418104d..f3eca221 100644 --- a/translations/dde-session-shell_es.ts +++ b/translations/dde-session-shell_es.ts @@ -3,7 +3,7 @@ AuthFace Face ID - ID de cara + ID facial Verification successful @@ -11,23 +11,23 @@ Verification failed, %n chances left - Verificación fallida, queda %n oportunidadVerificación fallida, quedan %n oportunidades + La verificación falló, queda %n oportunidadLa verificación falló, quedan %n oportunidadesLa verificación falló, quedan %n oportunidades Verification failed, only one chance left - Verificación fallida, sólo queda una oportunidad + La verificación falló, sólo queda una oportunidad Verify your Face ID - Verifique su ID de cara + Verifique su ID facial Face ID locked, use password please - ID de cara bloqueado, utilice la contraseña por favor + ID facial bloqueada, utilice la contraseña por favor Device unavailable! - + ¡Dispositivo no disponible! @@ -42,7 +42,7 @@ Verification failed, %n chances left - Verificación fallida, quedan %n oportunidadesVerificación fallida, quedan %n oportunidades + La verificación falló, queda %n oportunidadLa verificación falló, quedan %n oportunidadesLa verificación falló, quedan %n oportunidades Verification failed, only one chance left @@ -65,11 +65,11 @@ Verification failed, %n chances left - Verificación fallida, queda %n oportunidadVerificación fallida, quedan %n oportunidades + La verificación falló, queda %n oportunidadLa verificación falló, quedan %n oportunidadesLa verificación falló, quedan %n oportunidades Verification failed, only one chance left - Verificación fallida, sólo queda una oportunidad + La verificación falló, sólo queda una oportunidad Verify your Iris ID @@ -80,6 +80,25 @@ ID de Iris bloqueado, utilice la contraseña por favor + + AuthPasskey + + Please plug in the security key + Por favor ingrese la clave de seguridad + + + Verification successful + Verificación exitosa + + + Verification failed + La verificación falló + + + Identifying the security key + Identificando clave de seguridad + + AuthPassword @@ -88,7 +107,7 @@ Verification failed, %n chances left - Verificación fallida, queda %n oportunidadVerificación fallida, quedan %n oportunidades + La verificación falló, queda %n oportunidadLa verificación falló, quedan %n oportunidadesLa verificación falló, quedan %n oportunidades Verification failed, only one chance left @@ -108,7 +127,7 @@ Please try again %n minutes later - Por favor, inténtelo de nuevo %n minutos más tardePor favor, inténtelo de nuevo %n minutos más tarde + Por favor, inténtelo de nuevo en %n minuto más tardePor favor, inténtelo de nuevo en %n minutos más tardePor favor, inténtelo de nuevo en %n minutos más tarde Reset Password @@ -116,7 +135,7 @@ Forgot password? - ¿Ha olvidado su contraseña? + ¿Olvidó la contraseña? @@ -127,15 +146,15 @@ Please try again %n minutes later - Por favor, inténtelo de nuevo %n minutos más tardePor favor, inténtelo de nuevo %n minutos más tarde + Vuelva a intentarlo %n minuto más tardeVuelva a intentarlo %n minutos más tardeVuelva a intentarlo %n minutos más tarde Reset Password - Reestablecer contraseña + Restablecer contraseña Forgot password? - ¿Ha olvidado su contraseña? + ¿Olvidó la contraseña? @@ -146,7 +165,7 @@ Verification failed, %n chances left - Verificación fallida, queda %n oportunidadVerificación fallida, quedan %n oportunidades + La verificación falló, queda %n oportunidadLa verificación falló, quedan %n oportunidadesLa verificación falló, quedan %n oportunidades Verification failed, only one chance left @@ -166,7 +185,7 @@ Please try again %n minute(s) later - Por favor, inténtelo de nuevo %n minuto(s) más tardePor favor, inténtelo de nuevo %n minuto(s) más tarde + Por favor, inténtelo de nuevo %n minuto(s) más tardePor favor, inténtelo de nuevo %n minuto(s) más tardePor favor, inténtelo de nuevo %n minuto(s) más tarde Please try again 1 minute later @@ -174,7 +193,7 @@ Please try again %n minutes later - Por favor, inténtelo de nuevo %n minutos más tardePor favor, inténtelo de nuevo %n minutos más tarde + Por favor, inténtelo de nuevo en %n minuto más tardePor favor, inténtelo de nuevo en %n minutos más tardePor favor, inténtelo de nuevo en %n minutos más tarde @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - Su contraseña expirará en %n día, por favor, cámbiela a tiempoSu contraseña expirará en %n días, por favor, cámbiela a tiempo + Su contraseña expirará en %n día, por favor, cámbiela a tiempoSu contraseña expirará en %n días, por favor, cámbiela a tiempoSu contraseña expirará en %n días, por favor, cámbiela a tiempo Password expired, please change La contraseña ha caducado, por favor, cámbiela + + Your password has expired. Please contact the administrator to change it + Su contraseña ha caducado. Póngase en contacto con el administrador para cambiarla + + + Terminal locked, please contact administrator + Terminal bloqueada, comuníquese con el administrador + + + + DeepinAuthFramework + + Wrong Password + Contraseña Incorrecta + GreeterWorker @@ -209,6 +243,17 @@ Cancel Cancelar + + The reason of inhibit. + La razón de inhibir. + + + + LighterGreeter + + Standard Mode + Modo estándar + LockContent @@ -288,6 +333,14 @@ Switch system Cambiar sistema + + Update and Shut Down + Actualizar y apagar + + + Update and Reboot + Actualizar y reiniciar + SystemMonitor @@ -296,6 +349,55 @@ Iniciar el monitor del sistema + + UdcpMFALoginWidget + + 发送验证码 + Enviar código de verificación + + + 请输入手机号 + Por favor, introduzca el número de su teléfono móvil + + + 请输入验证码 + Por favor, introduzca el código de verificación + + + 获取验证码 + Obtener un código de verificación + + + + UpdateWorker + + Update + Actualizar + + + Please plug in and then install updates. + Conéctelo y luego instale las actualizaciones. + + + + UsersWithTheSameName + + Return + Regresar + + + Please select the account for login + Por favor seleccione la cuenta para iniciar sesión + + + Local Account + Cuenta local + + + Domain Account + Cuenta de dominio + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? ¿Seguro que desea cerrar sesión? + + Update and Shut Down + Actualizar y apagar + + + Update and Reboot + Actualizar y reiniciar + + + Closing the programs and shutting down, please wait... + Cerrando los programas y apagando, por favor espere… + + + Closing the programs and rebooting, please wait... + Cerrando los programas y reiniciando, por favor espere… + + + Closing the programs and logging out, please wait... + Cerrando los programas y cerrando la sesión, por favor espere... + + + + dss::module::AssistLoginWidget + + Automatic login + Inicio de sesión automático + dss::module::NetworkModule diff --git a/translations/dde-session-shell_et.ts b/translations/dde-session-shell_et.ts index e22085b9..8c8c1af6 100644 --- a/translations/dde-session-shell_et.ts +++ b/translations/dde-session-shell_et.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Sule arvuti + Verify your fingerprint + - - - - - Reboot - Taaskäivita + Verification successful + + + + Verification failed, %n chances left + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + Vale parool + + + Password + Parool + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Konto + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + - - Verify your fingerprint or password + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator - GreeterWorkek + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + Wrong Password + Vale parool + InhibitWarnView - Cancel - Tühista + Loobu + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel - Tühista + Loobu - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Sule arvuti - - Reboot Taaskäivita - - Suspend - - Hibernate + + Lock + Lukk + + + Log out + Logi välja + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 - - New password + 请输入验证码 - - Repeat password + 获取验证码 + + + + + UpdateWorker + + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to reboot + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the account + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - Please enter the password + Shut down + Sule arvuti + + + Reboot + Taaskäivita + + + Suspend - - - Please try again %n minute(s) later - + + Hibernate + + + + Log out + Logi välja + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_eu.ts b/translations/dde-session-shell_eu.ts new file mode 100644 index 00000000..50aeece9 --- /dev/null +++ b/translations/dde-session-shell_eu.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_fa.ts b/translations/dde-session-shell_fa.ts index 94bf9f54..34580480 100644 --- a/translations/dde-session-shell_fa.ts +++ b/translations/dde-session-shell_fa.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - این برنامه‌ها مانع از خاموش شدن کامپیوتر می‌شوند و اجبار به خاموش کردن ممکن است باعث از دست رفتن داده‌ها شود . + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - برای بستن برنامه ، روی لغو کلیک کرده و سپس برنامه را ببندید. + Verification successful + + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - این برنامه‌ها مانع از راه اندازی مجدد کامپیوتر می‌شوند و اجبار به راه اندازی مجدد ممکن است باعث از دست رفتن داده‌ها شود . + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - این برنامه‌ها مانع از تعلیق کامپیوتر می‌شوند و اجبار به تعلیق ممکن است باعث از دست رفتن داده‌ها شود . + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - این برنامه‌ها مانع از هایبرنت کامپیوتر می‌شوند و اجبار به هایبرنت ممکن است باعث از دست رفتن داده‌ها شود . + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - این برنامه‌ها مانع از خروج کامپیوتر می‌شوند و اجبار به خروج ممکن است باعث از دست رفتن داده‌ها شود . + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - خاموش شدن + Verify your fingerprint + - - - - - Reboot - راه اندازی مجدد + Verification successful + + + + Verification failed, %n chances left + - - - Suspend - معلق کردن + Verification failed, only one chance left + - - - Hibernate - هایبرنت + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - خارج شدن از حساب کاربری + Iris ID + - - Are you sure you want to shut down? - آیا از خاموشی مطمئن هستید ؟ + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - آیا از راه اندازی مجدد مطمئن هستید ؟ + Verification failed, only one chance left + - - Are you sure you want to log out? - آیا از خارج شدن مطمئن هستید ؟ + Verify your Iris ID + - - Lock - قفل + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - تغییر حساب کاربری + Please plug in the security key + - - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password رمزعبور اشتباه است - - The account or password is not correct. Please enter again. + Password + رمزعبور + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + حساب کاربری + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + رمز عبور منقضی شده است ، لطفا آن را عوض کنید + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + رمزعبور اشتباه است + InhibitWarnView - Cancel انصراف + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen قفل صفحه انجام نشد @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually تایید اثر انگشت منقضی شد , لطفا ً رمزعبور خود را دستی وارد کنید - Failed to match fingerprint تطابق اثر انگشت ناموفق بود - - - Wrong Password - رمزعبور اشتباه است - MultiUsersWarningView - Cancel انصراف - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? کاربران بالا هنوز داخل سیستم هستند و داده‌ها به دلیل خاموش شدن از دست خواهند رفت , آیا مطمئنید که می‌خواهید سیستم خاموش شود ؟ - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? کاربران بالا هنوز داخل سیستم هستند و داده‌ها به دلیل راه اندازی مجدد از دست خواهند رفت , آیا مطمئنید که می‌خواهید سیستم راه اندازی مجدد شود ؟ + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down خاموش شدن - - Reboot راه اندازی مجدد - - Suspend معلق کردن - - Hibernate هایبرنت + + Lock + قفل + + + Log out + خارج شدن از حساب کاربری + + + Switch user + تغییر حساب کاربری + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor آغاز پایش سیستم - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - رمز عبور منقضی شده است ، لطفا آن را عوض کنید + 发送验证码 + - - New password - رمز عبور جدید + 请输入手机号 + - - Repeat password - تکرار رمزعبور + 请输入验证码 + - - Failed to change your password - تغییر رمز عبور انجام نشد + 获取验证码 + + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - لطفا رمز عبور جدید را وارد کنید + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please repeat the new password - لطفا رمز عبور جدید دوباره را وارد کنید + Return + - - Passwords do not match - گذرواژه ها یکسان نیستند. + Please select the account for login + + + + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - رمزعبور + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + این برنامه‌ها مانع از خاموش شدن کامپیوتر می‌شوند و اجبار به خاموش کردن ممکن است باعث از دست رفتن داده‌ها شود . - - Account - حساب کاربری + To close the program, click Cancel, and then close the program. + برای بستن برنامه ، روی لغو کلیک کرده و سپس برنامه را ببندید. + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + این برنامه‌ها مانع از راه اندازی مجدد کامپیوتر می‌شوند و اجبار به راه اندازی مجدد ممکن است باعث از دست رفتن داده‌ها شود . + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + این برنامه‌ها مانع از تعلیق کامپیوتر می‌شوند و اجبار به تعلیق ممکن است باعث از دست رفتن داده‌ها شود . + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + این برنامه‌ها مانع از هایبرنت کامپیوتر می‌شوند و اجبار به هایبرنت ممکن است باعث از دست رفتن داده‌ها شود . + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + این برنامه‌ها مانع از خروج کامپیوتر می‌شوند و اجبار به خروج ممکن است باعث از دست رفتن داده‌ها شود . + + + Shut down + خاموش شدن + + + Reboot + راه اندازی مجدد + + + Suspend + معلق کردن + + + Hibernate + هایبرنت - - Please enter the account + Log out + خارج شدن از حساب کاربری + + + Are you sure you want to shut down? + آیا از خاموشی مطمئن هستید ؟ + + + Are you sure you want to reboot? + آیا از راه اندازی مجدد مطمئن هستید ؟ + + + Are you sure you want to log out? + آیا از خارج شدن مطمئن هستید ؟ + + + Update and Shut Down - - Please enter the password + Update and Reboot - - - Please try again %n minute(s) later - + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + روشن کردن + + + Turn off + خاموش کردن \ No newline at end of file diff --git a/translations/dde-session-shell_fi.ts b/translations/dde-session-shell_fi.ts index 67fc54e6..099fedfb 100644 --- a/translations/dde-session-shell_fi.ts +++ b/translations/dde-session-shell_fi.ts @@ -27,7 +27,7 @@ Device unavailable! - + Laite ei ole käytettävissä! @@ -80,6 +80,25 @@ Iriksen tunnistus lukittu, käytä salasanaa + + AuthPasskey + + Please plug in the security key + Liitä suojausavain + + + Verification successful + Tarkistus onnistui + + + Verification failed + Tarkistus epäonnistui + + + Identifying the security key + Suojausavaimella tunnistaminen + + AuthPassword @@ -191,6 +210,21 @@ Password expired, please change Salasana vanhentunut, vaihda + + Your password has expired. Please contact the administrator to change it + Salasanasi on vanhentunut. Ota yhteyttä järjestelmänvalvojaan muuttaaksesi sitä + + + Terminal locked, please contact administrator + Pääte on lukittu, ota yhteyttä järjestelmänvalvojaan + + + + DeepinAuthFramework + + Wrong Password + Väärä salasana + GreeterWorker @@ -209,6 +243,17 @@ Cancel Peruuta + + The reason of inhibit. + Estämisen syy. + + + + LighterGreeter + + Standard Mode + Vakiotila + LockContent @@ -225,7 +270,7 @@ LockWorker Fingerprint verification timed out, please enter your password manually - Sormenjäljen tarkistus aikakatkaistiin, ole hyvä ja anna salasana manuaalisesti + Sormenjäljen tarkistus aikakatkaistiin, ole hyvä ja anna salasana Failed to match fingerprint @@ -240,11 +285,11 @@ The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - Edellä mainitut käyttäjät ovat vielä kirjautuneet sisään ja tiedot katoavat, koska haluat sammuttaa? + Käyttäjiä on edelleen sisään kirjautuneena ja heidän avoimet työt katoavat. Haluatko varmasti sammuttaa? The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - Edellä mainitut käyttäjät ovat vielä kirjautuneet sisään ja tiedot katoavat uudelleenkäynnistyksen takia, haluatko varmasti uudelleenkäynnistyksen? + Käyttäjiä on edelleen sisään kirjautuneena ja heidän avoimet työt katoavat. Haluatko varmasti käynnistää uudelleen? @@ -288,6 +333,14 @@ Switch system Vaihda järjestelmää + + Update and Shut Down + Päivitä ja sammuta + + + Update and Reboot + Päivitä ja käynnistä + SystemMonitor @@ -296,15 +349,64 @@ Käynnistä järjestelmänhallinta + + UdcpMFALoginWidget + + 发送验证码 + Lähetä vahvistuskoodi + + + 请输入手机号 + Anna puhelinnumero + + + 请输入验证码 + Anna vahvistuskoodi + + + 获取验证码 + Hanki vahvistuskoodi + + + + UpdateWorker + + Update + Päivitä + + + Please plug in and then install updates. + Kytke sähköverkkoon ja asenna sitten päivitykset. + + + + UsersWithTheSameName + + Return + Palaa + + + Please select the account for login + Valitse tili kirjautumiseen + + + Local Account + Paikallinen tili + + + Domain Account + Toimialueen tili + + WarningContent The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Ohjelmat estävät tietokoneen sammutusta ja pakottaminen voi aiheuttaa tietojen menetyksen. + Ohjelmat estävät tietokoneen sammumisen. Pakottaminen voi aiheuttaa tietojen menetyksen. To close the program, click Cancel, and then close the program. - Valitse ensin Peruuta ja sulje sitten avoin ohjelma. + Paina ensin peruuta, sitten sulje avoin ohjelma. The programs are preventing the computer from reboot, and forcing reboot may cause data loss. @@ -354,6 +456,33 @@ Are you sure you want to log out? Haluatko kirjautua ulos? + + Update and Shut Down + Päivitä ja sammuta + + + Update and Reboot + Päivitä ja käynnistä + + + Closing the programs and shutting down, please wait... + Suljetaan ohjelmat ja sammutetaan, odota... + + + Closing the programs and rebooting, please wait... + Suljetaan ohjelmat ja käynnistetään uudelleen, odota... + + + Closing the programs and logging out, please wait... + Suljetaan ohjelmat ja kirjaudutaan ulos, odota... + + + + dss::module::AssistLoginWidget + + Automatic login + Kirjaudu automaattisesti + dss::module::NetworkModule diff --git a/translations/dde-session-shell_fil.ts b/translations/dde-session-shell_fil.ts index 24ab2a94..b0e6833d 100644 --- a/translations/dde-session-shell_fil.ts +++ b/translations/dde-session-shell_fil.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword - - Verify your fingerprint or password + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Password + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to reboot + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the account + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - Please enter the password + Shut down - - - Please try again %n minute(s) later - + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_fr.ts b/translations/dde-session-shell_fr.ts index 857a6b53..ef8e5339 100644 --- a/translations/dde-session-shell_fr.ts +++ b/translations/dde-session-shell_fr.ts @@ -1,9 +1,9 @@ - + - AuthFingerprint + AuthFace - Verify your fingerprint - Vérifier votre empreinte digitale + Face ID + Identification faciale Verification successful @@ -11,99 +11,103 @@ Verification failed, %n chances left - La vérification a échoué, il vous reste %n chanceLa vérification a échoué, il vous reste %n chances + La vérification a échoué, %n chance restanteLa vérification a échoué, %n chances restantes Verification failed, only one chance left La vérification a échoué, il ne vous reste plus qu'un seul essai - Fingerprint locked, use password please - Empreinte digitale verrouillée, veuillez utiliser le mot de passe, s'il vous plaît + Verify your Face ID + Vérifier votre identifiant de visage - - Please try again %n minute(s) later - Veuillez réessayer dans %n minute(s)Veuillez réessayer dans %n minute(s) + + Face ID locked, use password please + Face ID verrouillé, utiliser le mot de passe s'il vous plaît + + + Device unavailable! + Appareil indisponible ! - AuthPassword + AuthFingerprint + + Verify your fingerprint + Vérifier votre empreinte digitale + Verification successful Vérification réussie Verification failed, %n chances left - La vérification a échouée, il vous reste %n chanceLa vérification a échouée, il vous reste %n chances + La vérification a échoué, %n chance restanteLa vérification a échoué, %n chances restantesLa vérification a échoué, %n chances restantes Verification failed, only one chance left La vérification a échoué, il ne vous reste plus qu'un seul essai - Wrong Password - Mauvais mot de passe - - - Password - Mot de passe - - - Please try again %n minute(s) later - Veuillez réessayer dans %n minute(s)Veuillez réessayer dans %n minute(s) + Fingerprint locked, use password please + Empreinte digitale verrouillée, veuillez utiliser le mot de passe, s'il vous plaît - AuthSingle + AuthIris - Please try again 1 minute later - Veuillez réessayer dans 1 minute - - - Please try again %n minutes later - Veuillez réessayer dans %n minuteVeuillez réessayer dans %n minutes + Iris ID + ID d'iris - - - AuthUKey Verification successful Vérification réussie Verification failed, %n chances left - La vérification a échouée, il vous reste %n chanceLa vérification a échouée, il vous reste %n chances + La vérification a échoué, %n chance restanteLa vérification a échoué, %n chances restantesLa vérification a échoué, %n chances restantes Verification failed, only one chance left La vérification a échoué, il ne vous reste plus qu'un seul essai - Wrong PIN - Mauvais code PIN + Verify your Iris ID + Vérifier votre identifiant Iris - UKey is required - UKey est requis + Iris ID locked, use password please + Iris ID verrouillé, utilisez le mot de passe s'il vous plaît + + + AuthPasskey - Enter your PIN - Entrez votre code PIN + Please plug in the security key + Veuillez insérer la clé de sécurité. - - Please try again %n minute(s) later - Veuillez réessayer dans %n minute(s)Veuillez réessayer dans %n minute(s) + + Verification successful + Vérification réussie + + + Verification failed + Échec de la vérification + + + Identifying the security key + Identification de la clé de sécurité - AuthenticationModule + AuthPassword Verification successful Vérification réussie Verification failed, %n chances left - La vérification a échoué, il vous reste %n essaisLa vérification a échoué, il vous reste %n essais + La vérification a échoué, %n chance restanteLa vérification a échoué, %n chances restantesLa vérification a échoué, %n chances restantes Verification failed, only one chance left @@ -114,118 +118,123 @@ Mauvais mot de passe - Wrong PIN - Mauvais code PIN - - - UKey is required - UKey est requis + Password + Mot de passe - Verify your fingerprint - Vérifier votre empreinte digitale + Please try again 1 minute later + Veuillez réessayer dans 1 minute - - Password - Mot de passe + + Please try again %n minutes later + Veuillez réessayer %n minute plus tardVeuillez réessayer %n minutes plus tardVeuillez réessayer %n minutes plus tard - Enter your PIN - Entrez votre code PIN + Reset Password + réinitialiser le mot de passe - Fingerprint locked, use password please - Empreinte digitale verrouillée, veuillez utiliser le mot de passe, s'il vous plaît + Forgot password? + Mot de passe oublié ? + + + AuthSingle Please try again 1 minute later Veuillez réessayer dans 1 minute Please try again %n minutes later - Veuillez réessayer dans %n minuteVeuillez réessayer dans %n minutes + Veuillez réessayer %n minute plus tardVeuillez réessayer %n minutes plus tardVeuillez réessayer %n minutes plus tard - - - ContentWidget - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Les programmes empêchent l'ordinateur de s'éteindre, et le forcer à arrêter peut entraîner une perte de données. + Reset Password + Réinitialiser le mot de passe - To close the program, click Cancel, and then close the program. - Pour fermer le programme, cliquer sur Annuler, puis fermer le programme. + Forgot password? + Mot de passe oublié ? + + + AuthUKey - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Les programmes empêchent l'ordinateur de redémarrer et forcer le redémarrage peut entraîner une perte de données. + Verification successful + Vérification réussie - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Les programmes empêchent l'ordinateur de se mettre en veille, et forcer la mise en veille peut entraîner une perte de données. + + Verification failed, %n chances left + La vérification a échoué, %n chance restanteLa vérification a échoué, %n chances restantesLa vérification a échoué, %n chances restantes - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Les programmes empêchent l'ordinateur de se mettre en veille prolongée, et l'obliger à se mettre en veille prolongée peut entraîner une perte de données. + Verification failed, only one chance left + La vérification a échoué, il ne vous reste plus qu'un seul essai - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Les programmes empêchent l'ordinateur de se déconnecter et le fait de forcer la déconnexion peut entraîner une perte de données. + Wrong PIN + Mauvais code PIN - Shut down - Arrêter + UKey is required + UKey est requis - Reboot - Redémarrer + Enter your PIN + Entrer votre code PIN - - Suspend - Mise en veille + + Please try again %n minute(s) later + Veuillez réessayer %n minute plus tardVeuillez réessayer %n minute(s) plus tardVeuillez réessayer %n minute(s) plus tard - Hibernate - Mise en veille prolongée + Please try again 1 minute later + Veuillez réessayer dans 1 minute - - Log out - Déconnexion + + Please try again %n minutes later + Veuillez réessayer %n minute plus tardVeuillez réessayer %n minutes plus tardVeuillez réessayer %n minutes plus tard + + + AuthWidget - Are you sure you want to shut down? - Êtes-vous sûr de vouloir éteindre ? + Account + Compte - - Are you sure you want to reboot? - Êtes-vous sûr de vouloir redémarrer ? + + Your password will expire in %n days, please change it timely + Votre mot de passe expirera dans un jour, veuillez le changer à tempsVotre mot de passe expirera dans %n jours, veuillez le changer à tempsVotre mot de passe expirera dans %n jours, veuillez le changer à temps - Are you sure you want to log out? - Êtes-vous sûr de vouloir vous déconnecter ? + Password expired, please change + Mot de passe expiré, veuillez le modifier - Lock - Verrouiller + Your password has expired. Please contact the administrator to change it + Votre mot de passe a expiré, veuillez contacter votre administrateur pour le changer - Switch user - Changer d'utilisateur + Terminal locked, please contact administrator + Terminal verrouillé, veuillez contacter l'administrateur. + + + DeepinAuthFramework - Switch system - Changer de système + Wrong Password + Mauvais mot de passe - GreeterWorkek + GreeterWorker Wrong account Mauvais compte Wrong Password - Mauvais mot de passe + Mauvais mot de passe @@ -234,6 +243,17 @@ Cancel Annuler + + The reason of inhibit. + La raison de ce blocage. + + + + LighterGreeter + + Standard Mode + Mode standard + LockContent @@ -272,6 +292,13 @@ Les utilisateurs ci-dessus sont toujours connectés, des données seront perdues si vous redémarrez l'ordinateur, êtes-vous sûr de vouloir poursuivre? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + Vous avez activé le niveau de sécurité élevé du système, vous ne pouvez donc pas passer en mode Wayland, veuillez désactiver le niveau de sécurité élevé dans Security Center et réessayer. + + ShutdownWidget @@ -292,7 +319,7 @@ Lock - Fermer à clé + Verrouiller Log out @@ -306,6 +333,14 @@ Switch system Système de commutation + + Update and Shut Down + Mettre à jour puis éteindre + + + Update and Reboot + Mettre à jour puis redémarrer + SystemMonitor @@ -315,53 +350,83 @@ - UserLoginWidget + UdcpMFALoginWidget - Account - Compte + 发送验证码 + Envoyer le code de vérification - Verify your fingerprint - Vérifier votre empreinte digitale + 请输入手机号 + Veuillez saisir votre numéro de téléphone portable. - - Your password will expire in %n days, please change it timely - + + 请输入验证码 + Veuillez saisir le code de vérification - Password expired, please change - + 获取验证码 + Obtenir le code de vérification + + + + UpdateWorker + + Update + Mise à jour + + + Please plug in and then install updates. + Veuillez brancher l'appareil, puis installer les mises à jour. + + + + UsersWithTheSameName + + Return + Retour + + + Please select the account for login + Veuillez sélectionner le compte pour vous connecter. + + + Local Account + Compte local + + + Domain Account + Compte de domaine WarningContent The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Les programmes empêchent l'ordinateur de s'éteindre et forcer l'arrêt peut entraîner une perte de données. + Des programmes empêchent l'ordinateur de s'éteindre et forcer l'arrêt peut entraîner une perte de données. To close the program, click Cancel, and then close the program. - Pour fermer le programme, cliquez sur Annuler, puis fermez le programme. + Pour fermer le programme, cliquer sur Annuler, puis fermer le programme. The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Les programmes empêchent l'ordinateur de redémarrer et forcer le redémarrage peut entraîner une perte de données. + Des programmes empêchent l'ordinateur de redémarrer et forcer le redémarrage peut entraîner une perte de données. The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Les programmes empêchent l'ordinateur de se suspendre et forcer la suspension peut entraîner une perte de données. + Des programmes empêchent l'ordinateur de se suspendre et forcer la suspension peut entraîner une perte de données. The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Les programmes empêchent l'ordinateur de mettre en veille prolongée et forcer la mise en veille prolongée peut entraîner une perte de données. + Des programmes empêchent l'ordinateur de mettre en veille prolongée et forcer la mise en veille prolongée peut entraîner une perte de données. The programs are preventing the computer from log out, and forcing log out may cause data loss. - Les programmes empêchent l'ordinateur de se déconnecter et forcer la déconnexion peut entraîner une perte de données. + Des programmes empêchent l'ordinateur de se déconnecter et forcer la déconnexion peut entraîner une perte de données. Shut down - Eteindre + Éteindre Reboot @@ -381,7 +446,7 @@ Are you sure you want to shut down? - Êtes-vous sûr de vouloir arrêter ? + Êtes-vous sûr de vouloir éteindre ? Are you sure you want to reboot? @@ -391,5 +456,43 @@ Are you sure you want to log out? Êtes-vous sûr de vouloir vous déconnecter ? + + Update and Shut Down + Mettre à jour et arrêter + + + Update and Reboot + Mettre à jour et redémarrer + + + Closing the programs and shutting down, please wait... + Fermeture des programmes et arrêt du système, veuillez patienter... + + + Closing the programs and rebooting, please wait... + Fermeture des programmes et redémarrage, veuillez patienter... + + + Closing the programs and logging out, please wait... + Fermeture des programmes et déconnexion, veuillez patienter... + + + + dss::module::AssistLoginWidget + + Automatic login + Connexion automatique + + + + dss::module::NetworkModule + + Turn on + Allumer + + + Turn off + Éteindre + \ No newline at end of file diff --git a/translations/dde-session-shell_gl.ts b/translations/dde-session-shell_gl.ts new file mode 100644 index 00000000..1e3b93d0 --- /dev/null +++ b/translations/dde-session-shell_gl.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_gl_ES.ts b/translations/dde-session-shell_gl_ES.ts index 372f2a11..f6a301fb 100644 --- a/translations/dde-session-shell_gl_ES.ts +++ b/translations/dde-session-shell_gl_ES.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Os programas impiden que o ordenador se apague e forzar o apagado pode causar perda de datos. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Para pechar o programa, prema en Cancelar e logo pecha o programa. + Verification successful + Verificouse correctamente + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Os programas evitan que o computador se poida reiniciar e forzar o reinicio pode causar perda de datos. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Os programas impiden que o computador se suspenda e forzar a suspensión pode causar perda de datos. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Os programas están impedindo que a computadora hibernase e forzar a hibernación pode causar perda de datos. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Os programas impiden que o computador se saia e forzar a saída de sesión pode causar perda de datos. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Apagar + Verify your fingerprint + - - - - - Reboot - Reiniciar + Verification successful + Verificouse correctamente + + + Verification failed, %n chances left + - - - Suspend - Suspender + Verification failed, only one chance left + - - - Hibernate - Hibernar + Fingerprint locked, use password please + Bloqueado de pegadas dixitais, use o contrasinal + + + AuthIris - - - - Log out - Pechar a sesión + Iris ID + - - Are you sure you want to shut down? - Está seguro de que quere apagalo? + Verification successful + Verificouse correctamente + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Está seguro de que quere reiniciar? + Verification failed, only one chance left + - - Are you sure you want to log out? - Está seguro de que quere pechar sesión? + Verify your Iris ID + - - Lock - Bloquear + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Cambiar de usuario + Please plug in the security key + - - Switch system - Cambiar de sistema + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + Verificouse correctamente + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Contrasinal non válido - - The account or password is not correct. Please enter again. - A conta ou o contrasinal non son correctos. Introduce de novo. + Password + Contrasinal + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + Verificouse correctamente + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Conta + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Contrasinal caducado, cámbieo + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Contrasinal non válido InhibitWarnView - Cancel Cancelar + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Bloquear a pantalla - Failed to lock screen Erro ao bloquear a pantalla @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Rematou o tempo de verificación de pegadas dixitais. Introduce o seu contrasinal manualmente - Failed to match fingerprint Erro ao coincidir as pegadas dixitais - - - Wrong Password - Contrasinal non válido - MultiUsersWarningView - Cancel Cancelar - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Os usuarios anteriores aínda están conectados e os datos perdéranse por apagado, está seguro de que desexa pechar? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Os usuarios anteriores seguen conectados e os datos perderanse por reiniciar. Estás seguro de que queres reiniciar? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Apagar - - Reboot Reiniciar - - Suspend Suspender - - Hibernate Hibernar + + Lock + Bloquear + + + Log out + Pechar sesión + + + Switch user + Cambiar de usuario + + + Switch system + Cambiar de sistema + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - Comezar o sistema do monitor + Iniciar monitor do sistema - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Contrasinal caducado, cámbieo + 发送验证码 + - - New password - Novo contrasinal + 请输入手机号 + - - Repeat password - Repetir o contrasinal + 请输入验证码 + - - Failed to change your password - Erro ao cambiar o seu contrasinal + 获取验证码 + + + + UpdateWorker - - Password too weak - O contrasinal é demasiado débil + Update + - - Please enter the new password - Por favor, introduce o novo contrasinal + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + - - Please repeat the new password - Repetir o novo contrasinal + Please select the account for login + - - Passwords do not match - Os contrasinais non coinciden + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - Contrasinal + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Os programas impiden que o ordenador se apague e forzar o apagado pode causar perda de datos. - - Account - Conta + To close the program, click Cancel, and then close the program. + Para pechar o programa, prema en Cancelar e logo pecha o programa. - - Please enter the account - Insira unha conta + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Os programas evitan que o computador se poida reiniciar e forzar o reinicio pode causar perda de datos. - - Please enter the password - Insira un contrasinal + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Os programas impiden que o computador se suspenda e forzar a suspensión pode causar perda de datos. - - - Please try again %n minute(s) later - Volve a intentalo máis tarde %n minuto(s)Volve a intentalo máis tarde %n minuto(s) + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Os programas están impedindo que a computadora hibernase e forzar a hibernación pode causar perda de datos. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Os programas impiden que o computador se saia e forzar a saída de sesión pode causar perda de datos. + + + Shut down + Apagar + + + Reboot + Reiniciar + + + Suspend + Suspender + + + Hibernate + Hibernar + + + Log out + Pechar sesión + + + Are you sure you want to shut down? + Tes a certeza de querer apagar? + + + Are you sure you want to reboot? + Tes a certeza de querer reiniciar? + + + Are you sure you want to log out? + Tes a certeza de querer pechar a sesión? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Acender + + + Turn off + Apagar \ No newline at end of file diff --git a/translations/dde-session-shell_he.ts b/translations/dde-session-shell_he.ts index 9b0b543e..059ffbfd 100644 --- a/translations/dde-session-shell_he.ts +++ b/translations/dde-session-shell_he.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - כיבוי + Verify your fingerprint + - - - - - Reboot + Verification successful - - - - Suspend - השהיה + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out - התנתקות + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - נעילה + Verify your Iris ID + - - Switch user - החלף משתמש + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + - - Verify your fingerprint or password + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password סיסמא שגויה - - The domain account or password is not correct. Please enter again. + Password + ססמה + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + סיסמא שגויה + InhibitWarnView - Cancel ביטול + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - סיסמא שגויה - MultiUsersWarningView - Cancel ביטול - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down כיבוי - - Reboot - - Suspend השהיה - - Hibernate + תרדמת + + + Lock + נעילה + + + Log out + התנתקות + + + Switch user + החלף משתמש + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 - - New password + 请输入验证码 - - Repeat password + 获取验证码 + + + + + UpdateWorker + + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - ססמה + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + כיבוי + + + Reboot + + + + Suspend + השהיה + + + Hibernate + תרדמת + + + Log out + התנתקות + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_hi_IN.ts b/translations/dde-session-shell_hi_IN.ts index e8a71de1..abd6575c 100644 --- a/translations/dde-session-shell_hi_IN.ts +++ b/translations/dde-session-shell_hi_IN.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - बंद करें + Verify your fingerprint + - - - - - Reboot - पुनः आरंभ करें + Verification successful + - - - - Suspend - स्थगित करें + + Verification failed, %n chances left + - - - Hibernate - हाइबरनेट + Verification failed, only one chance left + - - - - Log out - लॉग आउट + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - लॉक स्क्रीन + Verify your Iris ID + - - Switch user - उपयोक्ता बदलें + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey - - Verify your fingerprint or password + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password गलत कूटशब्द - - The domain account or password is not correct. Please enter again. - डोमेन खाता या पासवर्ड सही नहीं है। कृपया फिर से दर्ज करें। + Password + कूटशब्द + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + गलत कूटशब्द InhibitWarnView - Cancel रद्द करें + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - डोमेन अकाउंट - - - Fingerprint verification timed out, please enter your password manually अंगुली-चिन्ह के सत्यापन का समय समाप्त हो गया है, कृपया मैनुअल रूप से कूटशब्द दर्ज़ करें - Failed to match fingerprint अंगुली-चिन्ह का मिलान असफल रहा - - - Wrong Password - गलत कूटशब्द - MultiUsersWarningView - Cancel रद्द करें - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down बंद करें - - Reboot पुनः आरंभ करें - - Suspend स्थगित करें - - Hibernate - हाइबरनेट + सुप्त करें + + + Lock + लॉक स्क्रीन + + + Log out + लॉग आउट + + + Switch user + उपयोक्ता बदलें + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + SystemMonitor - Start system monitor सिस्टम मॉनिटर शुरू करें - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - कूटशब्द पुनः दर्ज करें + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - कृपया नया पासवर्ड एंटर करें + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + - - Please repeat the new password + Please select the account for login - - Passwords do not match + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - कूटशब्द + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - पुनः आरंभ करने हेतु कूटशब्द दर्ज़ करें + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + बंद करें + + + Reboot + पुनः आरंभ करें + + + Suspend + स्थगित करें + + + Hibernate + सुप्त करें + + + Log out + लॉग आउट + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + ऑन करें + + + Turn off + ऑफ करें \ No newline at end of file diff --git a/translations/dde-session-shell_hr.ts b/translations/dde-session-shell_hr.ts index b533ebd2..adb69c72 100644 --- a/translations/dde-session-shell_hr.ts +++ b/translations/dde-session-shell_hr.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Ovi programi sprečavaju isključivanje računala, a prisilno isključivanje može uzrokovati gubitak podataka. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Za zatvaranje programa kliknite Otkaži i zatim zatvorite program. + Verification successful + Uspješna ovjera + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Ovi programi sprečavaju ponovno pokretanje računala, a prisilno ponovno pokretanje može uzrokovati gubitak podataka. + Verification failed, only one chance left + Neuspjela ovjera, preostala je samo jedna prilika - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Ovi programi sprečavaju odjavu računala, a prisilno odjavljivanje može uzrokovati gubitak podataka. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Isključi + Verify your fingerprint + Ovjerite vaš otisak prsta - - - - - Reboot - Ponovno podigni sustav + Verification successful + Uspješna ovjera + + + Verification failed, %n chances left + - - - Suspend - Suspendiraj + Verification failed, only one chance left + Neuspjela ovjera, preostala je samo jedna prilika - - - Hibernate - Hiberniraj + Fingerprint locked, use password please + Otisak prsta je zaključan, molim koristite lozinku + + + AuthIris - - - - Log out - Odjava + Iris ID + - - Are you sure you want to shut down? - Jeste li sigurni da želite isključiti? + Verification successful + Uspješna ovjera + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Jeste li sigurni da želite ponovno podignuti sustav? + Verification failed, only one chance left + Neuspjela ovjera, preostala je samo jedna prilika - - Are you sure you want to log out? - Jeste li sigurni da se želite odjaviti? + Verify your Iris ID + - - Lock - Zaključaj + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Promjeni korisnika + Please plug in the security key + - - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + Uspješna ovjera + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + Neuspjela ovjera, preostala je samo jedna prilika + - Wrong Password Pogrešna lozinka - - The account or password is not correct. Please enter again. - Račun ili lozinka nisu ispravni. Molim unesite ponovno. + Password + Lozinka + + + Please try again 1 minute later + Molim pokušajte ponovno nakon jedne minute + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + Zaboravili ste lozinku? + + + + AuthSingle + + Please try again 1 minute later + Molim pokušajte ponovno nakon jedne minute + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + Zaboravili ste lozinku? + + + + AuthUKey + + Verification successful + Uspješna ovjera + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + Neuspjela ovjera, preostala je samo jedna prilika + + + Wrong PIN + Pogrešni PIN + + + UKey is required + + + + Enter your PIN + Unesite vaš PIN + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + Molim pokušajte ponovno nakon jedne minute + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Račun + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Lozink je istekla, molim promijenite je + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + Pogrešni račun + + + Wrong Password + Pogrešna lozinka InhibitWarnView - Cancel Otkaži + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Zaključaj zaslon - Failed to lock screen Neuspjelo zaključavanje zaslona @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Isteklo je vrijeme ovjere otiska prsta, molim unesite lozinku ručno - Failed to match fingerprint Neuspjelo podudaranje otiska prsta - - - Wrong Password - Pogrešna lozinka - MultiUsersWarningView - Cancel Otkaži - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Gornji korisnici su još prijavljeni i podaci će biti izgubljeni zbog isključivanja računala, jeste li sigurni da želite isključiti računalo? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Gornji korisnici su još prijavljeni i podaci će biti izgubljeni zbog ponovnog podizanja sustava, jeste li sigurni da želite ponovno podići sustav? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Isključi - - Reboot Ponovno podigni sustav - - Suspend Suspendiraj - - Hibernate Hiberniraj + + Lock + Zaključaj + + + Log out + Odjava + + + Switch user + Promjeni korisnika + + + Switch system + Promijeni sustav + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Lozink je istekla, molim promijenite je + 发送验证码 + - - New password - Nova lozinka + 请输入手机号 + - - Repeat password - Ponovi lozinku + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + - - Failed to change your password - Neuspjela izmjena vaše lozinke + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - Lozinka je preslaba + Return + - - Please enter the new password - Unesite novu lozinku + Please select the account for login + - - Please repeat the new password - Molim ponovite novu lozinku + Local Account + - - Passwords do not match - Lozinka se ne podudara + Domain Account + - UserLoginWidget + WarningContent - - Password - Lozinka + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Ovi programi sprečavaju isključivanje računala, a prisilno isključivanje može uzrokovati gubitak podataka. - - Account - Račun + To close the program, click Cancel, and then close the program. + Za zatvaranje programa kliknite Otkaži i zatim zatvorite program. - - Please enter the account - Molim unesite račun + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Ovi programi sprečavaju ponovno pokretanje računala, a prisilno ponovno pokretanje može uzrokovati gubitak podataka. - - Please enter the password - Molim unesite lozinku + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Ovi programi sprečavaju odjavu računala, a prisilno odjavljivanje može uzrokovati gubitak podataka. + + + Shut down + Isključi + + + Reboot + Ponovno podigni sustav + + + Suspend + Suspendiraj + + + Hibernate + Hiberniraj + + + Log out + Odjava + + + Are you sure you want to shut down? + Jeste li sigurni da želite isključiti? + + + Are you sure you want to reboot? + Jeste li sigurni da želite ponovno podignuti sustav? + + + Are you sure you want to log out? + Jeste li sigurni da se želite odjaviti? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Uključi + + + Turn off + Isključi \ No newline at end of file diff --git a/translations/dde-session-shell_hu.ts b/translations/dde-session-shell_hu.ts index b41b8067..890bfa62 100644 --- a/translations/dde-session-shell_hu.ts +++ b/translations/dde-session-shell_hu.ts @@ -19,15 +19,15 @@ Verify your Face ID - Hitelesítés Arc azonosítóval + Hitelesítés Arcalapú azonosítással Face ID locked, use password please - Az Arc Azonosító zárolva, kérjük használja a jelszavát + Az Arcalapú azonosítás zárolva, kérjük használja a jelszavát Device unavailable! - + Az eszköz nem érhető el! @@ -73,11 +73,30 @@ Verify your Iris ID - Hitelesítés Írisz Azonosítóval + Hitelesítés Írisz Azonosítással Iris ID locked, use password please - Az Írisz Azonosító zárolva, kérjük használja a jelszavát + Az Írisz azonosítás zárolva, kérjük használja a jelszavát + + + + AuthPasskey + + Please plug in the security key + Kérjük csatlakoztassa a biztonsági kulcsot + + + Verification successful + Az ellenőrzés sikeres + + + Verification failed + Az ellenőrzés sikertelen + + + Identifying the security key + A biztonsági kulcs azonosítása @@ -191,6 +210,21 @@ Password expired, please change Jelszava lejárt, kérjük változtassa meg + + Your password has expired. Please contact the administrator to change it + A jelszava lejárt. A módosításhoz kérjük forduljon a Rendszergazdához. + + + Terminal locked, please contact administrator + A terminál zárolva van, forduljon a Rendszergazdához + + + + DeepinAuthFramework + + Wrong Password + Helytelen jelszó + GreeterWorker @@ -209,6 +243,17 @@ Cancel Mégsem + + The reason of inhibit. + A meggátolás oka: + + + + LighterGreeter + + Standard Mode + Általános Mód + LockContent @@ -225,11 +270,11 @@ LockWorker Fingerprint verification timed out, please enter your password manually - Ujjlenyomat azonosítás időtúllépése, kérjük adja meg a jelszót kézzel + Az ujjlenyomat azonosítás időtúllépése, kérjük adja meg a jelszavát kézzel Failed to match fingerprint - Ujjlenyomatok nem egyeznek + Az ujjlenyomatok nem egyeznek @@ -288,6 +333,14 @@ Switch system Rendszer váltása + + Update and Shut Down + Frissítés és Leállítás + + + Update and Reboot + Frissítés és Újraindítás + SystemMonitor @@ -296,6 +349,55 @@ Rendszermonitor indítása + + UdcpMFALoginWidget + + 发送验证码 + Küldje el az ellenőrző kódot + + + 请输入手机号 + Kérjük adja meg a telefonszámát + + + 请输入验证码 + Kérjük adja meg az ellenőrző kódot + + + 获取验证码 + Ellenőrző kódot kap + + + + UpdateWorker + + Update + Frissítés + + + Please plug in and then install updates. + Kérjük csatlakoztassa a számítógépet az áramforráshoz, majd telepítse a frissítéseket. + + + + UsersWithTheSameName + + Return + Vissza + + + Please select the account for login + Kérjük válasszon ki egy fiókot a bejelentkezéshez + + + Local Account + Helyi fiók + + + Domain Account + Tartományi fiók + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Biztosan ki akar jelentkezni? + + Update and Shut Down + Frissítés és Leállítás + + + Update and Reboot + Frissítés és Újraindítás + + + Closing the programs and shutting down, please wait... + A programok bezárása és leállítás, kérjük várjon... + + + Closing the programs and rebooting, please wait... + A programok bezárása és újraindítás, kérjük várjon... + + + Closing the programs and logging out, please wait... + A programok bezárása és kijelentkezés, kérjük várjon... + + + + dss::module::AssistLoginWidget + + Automatic login + Automatikus bejelentkezés + dss::module::NetworkModule diff --git a/translations/dde-session-shell_hy.ts b/translations/dde-session-shell_hy.ts index bd99d382..153989a1 100644 --- a/translations/dde-session-shell_hy.ts +++ b/translations/dde-session-shell_hy.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Անջատել + Verify your fingerprint + - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend - Ընդհատել + Verification failed, only one chance left + - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out - Դուրս գալ համակարգից + Iris ID + - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock - Փակել + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Փոխել օգտատերին + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + - - Verify your fingerprint or password + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? - GreeterWorkek + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel Չեղարկել + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel Չեղարկել - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Անջատել - - Reboot - - Suspend Ընդհատել - - Hibernate + + Lock + Փակել + + + Log out + Դուրս գալ համակարգից + + + Switch user + Փոխել օգտատերին + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Անջատել + + + Reboot + + + + Suspend + Ընդհատել + + + Hibernate + + + + Log out + Դուրս գալ համակարգից + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_id.ts b/translations/dde-session-shell_id.ts index df8cc726..e286f75a 100644 --- a/translations/dde-session-shell_id.ts +++ b/translations/dde-session-shell_id.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + Verifikasi berhasil + + + Verification failed, %n chances left + + + + Verification failed, only one chance left - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verify your Face ID - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Device unavailable! + + + AuthFingerprint - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Verify your fingerprint - - - - - Shut down - Matikan + Verification successful + Verifikasi berhasil + + + Verification failed, %n chances left + - - - - - Reboot - Boot ulang + Verification failed, only one chance left + - - - Suspend - Tangguhkan + Fingerprint locked, use password please + + + + AuthIris - - - Hibernate - Hibernasi + Iris ID + - - - - Log out - Keluar + Verification successful + Verifikasi berhasil + + + Verification failed, %n chances left + - - Are you sure you want to shut down? - Apakah Anda yakin ingin mematikan? + Verification failed, only one chance left + - - Are you sure you want to reboot? + Verify your Iris ID - - Are you sure you want to log out? - Apakah Anda yakin ingin keluar? + Iris ID locked, use password please + + + + AuthPasskey - - Lock - Kunci + Please plug in the security key + - - Switch user - Beralih pengguna + Verification successful + + + + Verification failed + + + + Identifying the security key + - DeepinAuthFramework + AuthPassword + + Verification successful + Verifikasi berhasil + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + Sandi lewat Salah + + + Password + Sandi lewat + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + Lupa kata sandi? + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + Lupa kata sandi? + + + + AuthUKey + + Verification successful + Verifikasi berhasil + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Akun + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + - - Verify your fingerprint or password + Terminal locked, please contact administrator - GreeterWorkek + DeepinAuthFramework - Wrong Password - Sandi lewat Salah + + + + + GreeterWorker + + Wrong account + - - The domain account or password is not correct. Please enter again. - Akun domain atau kata sandi tidak tepat. Mohon masukan kembali. + Wrong Password + Sandi lewat Salah InhibitWarnView - Cancel Batal + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - Akun Domain - - - Fingerprint verification timed out, please enter your password manually Waktu verifikasi sidik jari sudah habis, mohon masukan kata sandi anda secara manual - Failed to match fingerprint Gagal mencocokan sidik jari - - - Wrong Password - Sandi lewat Salah - MultiUsersWarningView - Cancel Batal - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Matikan - - Reboot Boot ulang - - Suspend Tangguhkan - - Hibernate Hibernasi + + Lock + Kunci + + + Log out + Keluar + + + Switch user + Beralih pengguna + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Mulai monitor sistem - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - Ulangi sandi lewat + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - Silakan masukkan kata sandi yang baru + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match - Sandi lewat tidak cocok + Please select the account for login + + + + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - Sandi lewat + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account - Akun + To close the program, click Cancel, and then close the program. + - - Enter your password to reboot - Masukkan sandi lewat Anda untuk muat ulang + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Matikan + + + Reboot + Boot ulang + + + Suspend + Tangguhkan + + + Hibernate + Hibernasi + + + Log out + Keluar + + + Are you sure you want to shut down? + Apakah Anda yakin ingin mematikan? + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + Apakah Anda yakin ingin keluar? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_id_ID.ts b/translations/dde-session-shell_id_ID.ts new file mode 100644 index 00000000..e052e8de --- /dev/null +++ b/translations/dde-session-shell_id_ID.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_it.ts b/translations/dde-session-shell_it.ts index d3098c1f..a56f2137 100644 --- a/translations/dde-session-shell_it.ts +++ b/translations/dde-session-shell_it.ts @@ -11,7 +11,7 @@ Verification failed, %n chances left - Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti + Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti Verification failed, only one chance left @@ -27,7 +27,7 @@ Device unavailable! - + Dispositivo non disponibile! @@ -42,7 +42,7 @@ Verification failed, %n chances left - Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti + Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti Verification failed, only one chance left @@ -65,7 +65,7 @@ Verification failed, %n chances left - Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti + Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti Verification failed, only one chance left @@ -80,6 +80,25 @@ Iris ID bloccato, utilizza la password per cortesia + + AuthPasskey + + Please plug in the security key + Per cortesia inserisci la chiave di sicurezza + + + Verification successful + Verifica completata con successo + + + Verification failed + Verifica fallita + + + Identifying the security key + Identificazione chiave di sicurezza + + AuthPassword @@ -88,7 +107,7 @@ Verification failed, %n chances left - Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti + Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti Verification failed, only one chance left @@ -108,7 +127,7 @@ Please try again %n minutes later - Riprova tra %n minutiRiprova tra %n minuti + Riprova tra %n minutiRiprova tra %n minutiRiprova tra %n minuti Reset Password @@ -127,7 +146,7 @@ Please try again %n minutes later - Riprova tra %n minutiRiprova tra %n minuti + Riprova tra %n minutiRiprova tra %n minutiRiprova tra %n minuti Reset Password @@ -146,7 +165,7 @@ Verification failed, %n chances left - Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti + Verifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanentiVerifica fallita, %n tentativi rimanenti Verification failed, only one chance left @@ -166,7 +185,7 @@ Please try again %n minute(s) later - Riprova tra %n minuto(i)Riprova tra %n minuto(i) + Riprova tra %n minuto(i)Riprova tra %n minuto(i)Riprova tra %n minuto(i) Please try again 1 minute later @@ -174,7 +193,7 @@ Please try again %n minutes later - Riprova tra %n minutiRiprova tra %n minuti + Riprova tra %n minutiRiprova tra %n minutiRiprova tra %n minuti @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - La tua password scadrà in %n giorni, ricordati di sostituirlaLa tua password scadrà in %n giorni, ricordati di sostituirla + La tua password scadrà tra %n giorni, cambiala tempestivamenteLa tua password scadrà tra %n giorni, cambiala tempestivamenteLa tua password scadrà tra %n giorni, cambiala tempestivamente Password expired, please change Password scaduta, cambiala per cortesia + + Your password has expired. Please contact the administrator to change it + La tua password è scaduta, contatta il tuo admin + + + Terminal locked, please contact administrator + Terminale bloccato, contatta il tuo admin + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,6 +243,17 @@ Cancel Annulla + + The reason of inhibit. + Il motivo dell'inibizione. + + + + LighterGreeter + + Standard Mode + Modalità standard + LockContent @@ -288,6 +333,14 @@ Switch system Cambia Sistema + + Update and Shut Down + Aggiorna e spegni + + + Update and Reboot + Aggiorna e riavvia + SystemMonitor @@ -296,6 +349,55 @@ Avvia il System Monitor + + UdcpMFALoginWidget + + 发送验证码 + Invia il codice di verifica + + + 请输入手机号 + Inserisci il numero di telefono + + + 请输入验证码 + Inserisci il codice di verifica + + + 获取验证码 + Richiedi il codice di verifica + + + + UpdateWorker + + Update + Aggiorna + + + Please plug in and then install updates. + Per cortesia collega l'alimentatore per installare gli aggiornamenti. + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Sicuro di voler terminare la sessione? + + Update and Shut Down + Aggiorna e spegni. + + + Update and Reboot + Aggiorna e riavvia + + + Closing the programs and shutting down, please wait... + Chiusura delle applicazioni per poter spegnere il computer, attendere... + + + Closing the programs and rebooting, please wait... + Chiusura delle applicazioni per poter riavviare il computer, attendere... + + + Closing the programs and logging out, please wait... + Chiusura delle applicazioni per poter uscire dalla sessione di Sistema, attendere... + + + + dss::module::AssistLoginWidget + + Automatic login + Login automatico + dss::module::NetworkModule diff --git a/translations/dde-session-shell_ja.ts b/translations/dde-session-shell_ja.ts index 3db34626..41f2adec 100644 --- a/translations/dde-session-shell_ja.ts +++ b/translations/dde-session-shell_ja.ts @@ -1,297 +1,498 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + 認証完了 + + + Verification failed, %n chances left + + + + Verification failed, only one chance left - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verify your Face ID - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Device unavailable! + + + AuthFingerprint - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Verify your fingerprint + 指紋で認証 + + + Verification successful + 認証完了 + + + Verification failed, %n chances left + + + + Verification failed, only one chance left - - - - - Shut down - シャットダウン + Fingerprint locked, use password please + 指紋がロックされています。パスワードを使用してください + + + AuthIris - - - - - Reboot - 再起動 + Iris ID + - - - Suspend - サスペンド + Verification successful + 認証完了 + + + Verification failed, %n chances left + - - - Hibernate - ハイバーネート + Verification failed, only one chance left + - - - - Log out - ログアウト + Verify your Iris ID + - - Are you sure you want to shut down? - シャットダウンしてもよろしいですか? + Iris ID locked, use password please + + + + AuthPasskey - - Are you sure you want to reboot? - 再起動してもよろしいですか? + Please plug in the security key + - - Are you sure you want to log out? - ログアウトしてもよろしいですか? + Verification successful + - - Lock - ロック + Verification failed + - - Switch user - ユーザーを切り替え + Identifying the security key + - DeepinAuthFramework + AuthPassword + + Verification successful + 認証完了 + + + Verification failed, %n chances left + + - - Verify your fingerprint or password - 指紋またはパスワードを確認してください + Verification failed, only one chance left + + + + Wrong Password + パスワードが違います + + + Password + パスワード + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + パスワードをリセット + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + 1分後にやり直してください + + + Please try again %n minutes later + %n分後にやり直してください + + + Reset Password + パスワードをリセット + + + Forgot password? + + + + + AuthUKey + + Verification successful + 認証完了 + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + - GreeterWorkek + AuthWidget + + Account + アカウント + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + パスワードの期限が切れています。変更してください + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password - パスワードが違います + + + + + GreeterWorker + + Wrong account + - - The domain account or password is not correct. Please enter again. - ドメインアカウントまたはパスワードが違います。もう一度入力してください。 + Wrong Password + パスワードが違います InhibitWarnView - Cancel キャンセル + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - + 画面をロック - Failed to lock screen - + 画面のロックに失敗しました LockWorker - - Domain account - ドメインアカウント - - - Fingerprint verification timed out, please enter your password manually 指紋認証がタイムアウトしました。パスワードを手入力してください - Failed to match fingerprint - 指紋が一致しませんでした - - - - Wrong Password - パスワードが違います + 指紋が一致しません MultiUsersWarningView - Cancel キャンセル - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? 現在上記のユーザーがまだログインしているため、シャットダウンによりこのデータが失われます。シャットダウンしてもよろしいですか? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? 上記のユーザーがまだログインしているため、再起動によりこのデータが失われます。再起動してもよろしいですか? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down シャットダウン - - Reboot 再起動 - - Suspend サスペンド - - Hibernate - ハイバーネート + ハイバネート + + + Lock + ロック + + + Log out + ログアウト + + + Switch user + ユーザーを切り替え + + + Switch system + システムを切り替え + + + Update and Shut Down + アップデートしてシャットダウン + + + Update and Reboot + アップデートして再起動 SystemMonitor - Start system monitor システムモニターを開始 - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - パスワードを再入力 + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + アップデート + + + Please plug in and then install updates. + アップデートをインストールするには、電源に接続してください。 + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password - 新しいパスワードを入力してください + Please select the account for login + - - Please repeat the new password + Local Account - - Passwords do not match - パスワードが一致しません + Domain Account + - UserLoginWidget + WarningContent - - Password - パスワード + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + プログラムがコンピューターのシャットダウンを妨げています。強制的にシャットダウンすると、データが失われる可能性があります。 - - Account - アカウント + To close the program, click Cancel, and then close the program. + プログラムを終了するには、キャンセルをクリックして、プログラムを終了してください。 + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + プログラムがコンピューターの再起動を妨げています。強制的に再起動すると、データが失われる可能性があります。 + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + プログラムがコンピューターのサスペンドを妨げています。強制的にサスペンドすると、データが失われる可能性があります。 + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + プログラムがコンピューターのハイバネートを妨げています。強制的にハイバネートにすると、データが失われる可能性があります。 + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + プログラムがコンピューターのログアウトを妨げています。強制的にログアウトすると、データが失われる可能性があります。 + + + Shut down + シャットダウン + + + Reboot + 再起動 + + + Suspend + サスペンド + + + Hibernate + ハイバーネート + + + Log out + ログアウト + + + Are you sure you want to shut down? + シャットダウンしてもよろしいですか? + + + Are you sure you want to reboot? + 再起動してもよろしいですか? + + + Are you sure you want to log out? + ログアウトしてもよろしいですか? - - Enter your password to reboot - 再起動するにはパスワードを入力してください + Update and Shut Down + アップデートしてシャットダウン - - Enter your password to shut down - シャットダウンするにはパスワードを入力してください + Update and Reboot + アップデートして再起動 - - Please enter the account + Closing the programs and shutting down, please wait... - - Please enter the password + Closing the programs and rebooting, please wait... - - - Please try again %n minute(s) later - %n 分後に、もう一度お試しください + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + オンにする + + + Turn off + オフにする \ No newline at end of file diff --git a/translations/dde-session-shell_ka.ts b/translations/dde-session-shell_ka.ts new file mode 100644 index 00000000..518f6b00 --- /dev/null +++ b/translations/dde-session-shell_ka.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + პაროლი + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + გაუქმება + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + გაუქმება + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + გადატვირთვა + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + გადატვირთვა + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_kab.ts b/translations/dde-session-shell_kab.ts new file mode 100644 index 00000000..82b61dd2 --- /dev/null +++ b/translations/dde-session-shell_kab.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + Yir awal uffir + + + Password + Awal uffir + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Yir awal uffir + + + + InhibitWarnView + + Cancel + Sefsex + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + Amṣada n udsil umḍin yecceḍ + + + + MultiUsersWarningView + + Cancel + Sefsex + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + Sens + + + Reboot + Ales asker + + + Suspend + Seḥbes + + + Hibernate + + + + Lock + Sekkeṛ + + + Log out + Ffeɣ + + + Switch user + Senfel aseqdac + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + Senkar asefrak n unagraw + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + Sens + + + Reboot + Ales asker + + + Suspend + Seḥbes + + + Hibernate + + + + Log out + Ffeɣ + + + Are you sure you want to shut down? + D tidet tebɣiḍ ad ttesḥebseḍ? + + + Are you sure you want to reboot? + D tidet tebɣiḍ ad talseḍ asenker? + + + Are you sure you want to log out? + D tidet tebɣiḍ ad teffɣeḍ? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Sermed + + + Turn off + Sens + + + \ No newline at end of file diff --git a/translations/dde-session-shell_kk.ts b/translations/dde-session-shell_kk.ts new file mode 100644 index 00000000..3eb05185 --- /dev/null +++ b/translations/dde-session-shell_kk.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Пароль + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + Бас тарту + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + Бас тарту + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_km_KH.ts b/translations/dde-session-shell_km_KH.ts new file mode 100644 index 00000000..eb4965c7 --- /dev/null +++ b/translations/dde-session-shell_km_KH.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + បោះបង់ + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + បោះបង់ + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + បិទ + + + Reboot + ចាប់ផ្តើមឡើងវិញ + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + បិទ + + + Reboot + ចាប់ផ្តើមឡើងវិញ + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_kn_IN.ts b/translations/dde-session-shell_kn_IN.ts new file mode 100644 index 00000000..b1adfc26 --- /dev/null +++ b/translations/dde-session-shell_kn_IN.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ko.ts b/translations/dde-session-shell_ko.ts index 03fe2b82..c42a8d00 100644 --- a/translations/dde-session-shell_ko.ts +++ b/translations/dde-session-shell_ko.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - 이 프로그램이 컴퓨터를 종료하지 못하게 하고 있으며, 강제로 종료하면 데이터가 손실될 수 있습니다. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - 프로그램을 닫려면 취소를 클릭한 다음 프로그램을 닫습니다. + Verification successful + 확인 성공 + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - 이 프로그램이 컴퓨터를 재부팅하지 못하게 하고 있으며, 강제로 재부팅하면 데이터가 손실될 수 있습니다. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - 이 프로그램은 컴퓨터가 일시 중단되는 것을 방지하고, 강제로 일시 중단하면 데이터 손실이 발생할 수 있습니다. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - 이 프로그램으로 인해 컴퓨터가 최대 절전 모드로 전환되지 않으며, 최대 절전 모드로 전환하면 데이터가 손실될 수 있습니다. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - 이 프로그램으로 인해 컴퓨터가 로그아웃되지 않으며, 강제로 로그아웃하면 데이터가 손실될 수 있습니다. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - 컴퓨터 끄기 + Verify your fingerprint + - - - - - Reboot - 재부팅 + Verification successful + 확인 성공 + + + Verification failed, %n chances left + - - - Suspend - 대기모드 + Verification failed, only one chance left + - - - Hibernate - 최대 절전 모드 + Fingerprint locked, use password please + 지문 잠김, 비밀번호를 사용하십시오 + + + AuthIris - - - - Log out - 로그아웃 + Iris ID + - - Are you sure you want to shut down? - 종료 하시겠습니까? + Verification successful + 확인 성공 + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - 재부팅 하시겠습니까? + Verification failed, only one chance left + - - Are you sure you want to log out? - 로그 아웃 하시겠습니까? + Verify your Iris ID + - - Lock - 잠금 + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - 사용자 전환 + Please plug in the security key + - - Switch system - 전환 시스템 + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + 확인 성공 + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password 잘못된 비밀번호 - - The account or password is not correct. Please enter again. - 계정 또는 비밀번호가 올바르지 않습니다. 다시 입력하십시오. + Password + 비밀번호 + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + 비밀번호 초기화 + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + 비밀번호 초기화 + + + Forgot password? + + + + + AuthUKey + + Verification successful + 확인 성공 + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + 계정 + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + 비밀번호가 만료되었습니다. 변경하십시오 + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + 잘못된 비밀번호 InhibitWarnView - Cancel 취소 + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen 잠금 화면 - Failed to lock screen 화면 잠금 실패 @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually 지문 확인 시간이 초과되었습니다. 비밀번호를 직접 입력하여 주십시오. - Failed to match fingerprint 지문 일치 실패 - - - Wrong Password - 잘못된 비밀번호 - MultiUsersWarningView - Cancel 취소 - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? 위의 사용자가 여전히 로그인되어 있고 종료로 인해 데이터가 손실됩니다. 종료하시겠습니까? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? 위의 사용자가 계속 로그인되어 있고 재부팅으로 인해 데이터가 손실됩니다. 재부팅하시겠습니까? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down 컴퓨터 끄기 - - Reboot 재부팅 - - Suspend 대기모드 - - Hibernate 최대 절전 모드 + + Lock + 잠금 + + + Log out + 로그아웃 + + + Switch user + 사용자 전환 + + + Switch system + 전환 시스템 + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor 시스템 모니터링 시작하기 - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - 비밀번호가 만료되었습니다. 변경하십시오 + 发送验证码 + + + + 请输入手机号 + - - New password - 새 비밀번호 + 请输入验证码 + - - Repeat password - 비밀번호 반복 + 获取验证码 + + + + + UpdateWorker + + Update + - - Failed to change your password - 비밀번호를 변경하지 못했습니다 + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - 비밀번호가 너무 약합니다 + Return + - - Please enter the new password - 새 비밀번호를 입력하십시오 + Please select the account for login + - - Please repeat the new password - 새 비밀번호를 반복하십시오 + Local Account + - - Passwords do not match - 비밀번호가 일치하지 않습니다 + Domain Account + - UserLoginWidget + WarningContent - - Password - 비밀번호 + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + 이 프로그램이 컴퓨터를 종료하지 못하게 하고 있으며, 강제로 종료하면 데이터가 손실될 수 있습니다. - - Account - 계정 + To close the program, click Cancel, and then close the program. + 프로그램을 닫려면 취소를 클릭한 다음 프로그램을 닫습니다. - - Please enter the account - 계정을 입력하십시오 + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + 이 프로그램이 컴퓨터를 재부팅하지 못하게 하고 있으며, 강제로 재부팅하면 데이터가 손실될 수 있습니다. - - Please enter the password - 비밀번호를 입력하십시오 + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + 이 프로그램은 컴퓨터가 일시 중단되는 것을 방지하고, 강제로 일시 중단하면 데이터 손실이 발생할 수 있습니다. - - - Please try again %n minute(s) later - %n분 후에 다시 시도하십시오 + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + 이 프로그램으로 인해 컴퓨터가 최대 절전 모드로 전환되지 않으며, 최대 절전 모드로 전환하면 데이터가 손실될 수 있습니다. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + 이 프로그램으로 인해 컴퓨터가 로그아웃되지 않으며, 강제로 로그아웃하면 데이터가 손실될 수 있습니다. + + + Shut down + 컴퓨터 끄기 + + + Reboot + 재부팅 + + + Suspend + 대기모드 + + + Hibernate + 최대 절전 모드 + + + Log out + 로그아웃 + + + Are you sure you want to shut down? + 종료 하시겠습니까? + + + Are you sure you want to reboot? + 재부팅 하시겠습니까? + + + Are you sure you want to log out? + 로그 아웃 하시겠습니까? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + 켜기 + + + Turn off + 끄기 \ No newline at end of file diff --git a/translations/dde-session-shell_ku.ts b/translations/dde-session-shell_ku.ts index 7e70fe15..7c0add35 100644 --- a/translations/dde-session-shell_ku.ts +++ b/translations/dde-session-shell_ku.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Bigire + Verify your fingerprint + - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out - Derkeve + Iris ID + - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Peyvborîn + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + - - Verify your fingerprint or password + Terminal locked, please contact administrator - GreeterWorkek + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel Betal Bike + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel Betal Bike - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Bigire - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + Derkeve + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - Peyvborînê dîsa binivîsîne + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Peyvborîn + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Bigire + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + Derkeve + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ku_IQ.ts b/translations/dde-session-shell_ku_IQ.ts index ee18e1c7..c22e5c8e 100644 --- a/translations/dde-session-shell_ku_IQ.ts +++ b/translations/dde-session-shell_ku_IQ.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + - - Verify your fingerprint or password + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel پاشگەزبوونەوە + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel پاشگەزبوونەوە - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ky.ts b/translations/dde-session-shell_ky.ts index c1410d11..ba3bffc2 100644 --- a/translations/dde-session-shell_ky.ts +++ b/translations/dde-session-shell_ky.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + - - Verify your fingerprint or password + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel жокко чыгаруу + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel жокко чыгаруу - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ky@Arab.ts b/translations/dde-session-shell_ky@Arab.ts index e2179c80..f15f02ca 100644 --- a/translations/dde-session-shell_ky@Arab.ts +++ b/translations/dde-session-shell_ky@Arab.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + - - Verify your fingerprint or password + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel جوققو چىعارۇۇ + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel جوققو چىعارۇۇ - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_la.ts b/translations/dde-session-shell_la.ts new file mode 100644 index 00000000..ce56c5b8 --- /dev/null +++ b/translations/dde-session-shell_la.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_lo.ts b/translations/dde-session-shell_lo.ts index f1a13182..ace21c7a 100644 --- a/translations/dde-session-shell_lo.ts +++ b/translations/dde-session-shell_lo.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - ປິດ​ເຄື່ອງ + Verify your fingerprint + - - - - - Reboot - ເປີດຄືນ + Verification successful + - - - - Suspend - ຢຸດໄວ້ + + Verification failed, %n chances left + - - - Hibernate - ນອນ + Verification failed, only one chance left + - - - - Log out - ອອກ​ຈາກ​ລະ​ບົບ + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - ລ໊ອກ + Verify your Iris ID + - - Switch user - ປ່ຽນຜູ້ໃຊ້ + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + - - Verify your fingerprint or password + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password ລະຫັດພ່ານຜິດ - - The domain account or password is not correct. Please enter again. + Password + ລະຫັດພ່ານ + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + ລະຫັດພ່ານຜິດ + + InhibitWarnView - Cancel ຍົກເລີກ + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - ລະຫັດພ່ານຜິດ - MultiUsersWarningView - Cancel ຍົກເລີກ - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down ປິດ​ເຄື່ອງ - - Reboot ເປີດຄືນ - - Suspend ຢຸດໄວ້ - - Hibernate ນອນ + + Lock + ລ໊ອກ + + + Log out + ອອກ​ຈາກ​ລະ​ບົບ + + + Switch user + ປ່ຽນຜູ້ໃຊ້ + + + Switch system + ປ່ຽນລະບົບ + + + Update and Shut Down + ອັບເດດ ແລະ ປິດເຄື່ອງ + + + Update and Reboot + ອັບເດດ ແລະ ເປີດຄືນ + SystemMonitor - Start system monitor - + ເປີດຕົວຕິດຕາມລະບົບ - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + ປັບປຸງໃຫ້ທັນ + - - Password too weak + Please plug in and then install updates. + ກະລຸນາສຽບແລະຫຼັງຈາກນັ້ນຕິດຕັ້ງການປັບປຸງ. + + + + UsersWithTheSameName + + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - ລະຫັດພ່ານ + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - ປ້ອນລະຫັດພ່ານຂອງເຈົ້າເພື່ອເປີດລະບົບຄືນ + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + ປິດ​ເຄື່ອງ + + + Reboot + ເປີດຄືນ + + + Suspend + ຢຸດໄວ້ + + + Hibernate + ນອນ + + + Log out + ອອກ​ຈາກ​ລະ​ບົບ + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_lt.ts b/translations/dde-session-shell_lt.ts index b8add1a3..93918b61 100644 --- a/translations/dde-session-shell_lt.ts +++ b/translations/dde-session-shell_lt.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Kai kurios programos neleidžia kompiuteriui išsijungti, o priverstinai išjungiant, gali būti prarasti duomenys. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Norėdami užverti programą, spustelėkite Atsisakyti, o tuomet užverkite programą. + Verification successful + + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Kai kurios programos neleidžia kompiuteriui pasileisti iš naujo, o priverstinai paleidžiant iš naujo, gali būti prarasti duomenys. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Kai kurios programos neleidžia kompiuteriui būti pristabdytam, o priverstinai pristabdant, gali būti prarasti duomenys. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Kai kurios programos neleidžia kompiuteriui būti užmigdytam, o priverstinai užmigdant, gali būti prarasti duomenys. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Kai kurios programos neleidžia kompiuteriui atsijungti, o priverstinai atsijungiant, gali būti prarasti duomenys. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Išjungti + Verify your fingerprint + - - - - - Reboot - Paleisti iš naujo + Verification successful + + + + Verification failed, %n chances left + - - - Suspend - Pristabdyti + Verification failed, only one chance left + - - - Hibernate - Užmigdyti + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - Atsijungti + Iris ID + - - Are you sure you want to shut down? - Ar tikrai norite išjungti? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Ar tikrai norite paleisti iš naujo? + Verification failed, only one chance left + - - Are you sure you want to log out? - Ar tikrai norite atsijungti? + Verify your Iris ID + - - Lock - Užrakinti + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Perjungti naudotoją + Please plug in the security key + - - Switch system + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Neteisingas slaptažodis - - The account or password is not correct. Please enter again. + Password + Slaptažodis + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Paskyra + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Slaptažodis nebegalioja, prašome jį pasikeisti + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker + + Wrong account + + + + Wrong Password + Neteisingas slaptažodis + + InhibitWarnView - Cancel Atsisakyti + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen Nepavyko užrakinti ekrano @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Pasibaigė piršto atspaudo patvirtinimui skirtas laikas, įveskite slaptažodį rankiniu būdu - Failed to match fingerprint Nepavyko sutapatinti piršto atspaudo - - - Wrong Password - Neteisingas slaptažodis - MultiUsersWarningView - Cancel Atsisakyti - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Aukščiau išvardyti naudotojai yra vis dar prisijungę ir dėl išjungimo praras duomenis, ar tikrai norite išjungti? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Aukščiau išvardyti naudotojai yra vis dar prisijungę ir dėl paleidimo iš naujo praras duomenis, ar tikrai norite paleisti iš naujo? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Išjungti - - Reboot Paleisti iš naujo - - Suspend Pristabdyti - - Hibernate Užmigdyti + + Lock + Užrakinti + + + Log out + Atsijungti + + + Switch user + Perjungti naudotoją + + + Switch system + Perjungti sistemą + + + Update and Shut Down + Atnaujinti ir išjungti + + + Update and Reboot + Atnaujinti ir paleisti iš naujo + SystemMonitor - Start system monitor Paleisti sistemos monitorių - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Slaptažodis nebegalioja, prašome jį pasikeisti + 发送验证码 + - - New password - Naujas slaptažodis + 请输入手机号 + - - Repeat password - Pakartokite slaptažodį + 请输入验证码 + - - Failed to change your password - Nepavyko pakeisti jūsų slaptažodžio + 获取验证码 + + + + UpdateWorker - - Password too weak + Update - - Please enter the new password - Prašome įrašyti naują slaptažodį + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please repeat the new password - Pakartokite naują slaptažodį + Return + - - Passwords do not match - Slaptažodžiai nesutampa + Please select the account for login + + + + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - Slaptažodis + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Kai kurios programos neleidžia kompiuteriui išsijungti, o priverstinai išjungiant, gali būti prarasti duomenys. - - Account - Paskyra + To close the program, click Cancel, and then close the program. + Norėdami užverti programą, spustelėkite Atsisakyti, o tuomet užverkite programą. + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Kai kurios programos neleidžia kompiuteriui pasileisti iš naujo, o priverstinai paleidžiant iš naujo, gali būti prarasti duomenys. + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Kai kurios programos neleidžia kompiuteriui būti pristabdytam, o priverstinai pristabdant, gali būti prarasti duomenys. + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Kai kurios programos neleidžia kompiuteriui būti užmigdytam, o priverstinai užmigdant, gali būti prarasti duomenys. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Kai kurios programos neleidžia kompiuteriui atsijungti, o priverstinai atsijungiant, gali būti prarasti duomenys. + + + Shut down + Išjungti + + + Reboot + Paleisti iš naujo + + + Suspend + Pristabdyti + + + Hibernate + Užmigdyti - - Please enter the account + Log out + Atsijungti + + + Are you sure you want to shut down? + Ar tikrai norite išjungti? + + + Are you sure you want to reboot? + Ar tikrai norite paleisti iš naujo? + + + Are you sure you want to log out? + Ar tikrai norite atsijungti? + + + Update and Shut Down + Atnaujinti ir išjungti + + + Update and Reboot + Atnaujinti ir paleisti iš naujo + + + Closing the programs and shutting down, please wait... - - Please enter the password + Closing the programs and rebooting, please wait... - - - Please try again %n minute(s) later - + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Įjungti + + + Turn off + Išjungti \ No newline at end of file diff --git a/translations/dde-session-shell_lv.ts b/translations/dde-session-shell_lv.ts index d8a4370f..0991e123 100644 --- a/translations/dde-session-shell_lv.ts +++ b/translations/dde-session-shell_lv.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Izslēgt + Verify your fingerprint + - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out - Izrakstīties + Iris ID + - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + - - Verify your fingerprint or password + Verification failed, only one chance left + + Wrong Password + + + + Password + Parole + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + - GreeterWorkek + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel Atcelt + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel Atcelt - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Izslēgt - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + Izrakstīties + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Parole + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Izslēgt + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + Izrakstīties + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ml.ts b/translations/dde-session-shell_ml.ts index b18fc0ff..c89cf5ef 100644 --- a/translations/dde-session-shell_ml.ts +++ b/translations/dde-session-shell_ml.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - നിർത്തുക + Verify your fingerprint + - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword - - Verify your fingerprint or password + Verification successful + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + തെറ്റായ രഹസ്യവാക്ക് + + + Password + രഹസ്യവാക്ക് + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + - GreeterWorkek + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password - തെറ്റായ രഹസ്യവാക്ക് + + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + Wrong Password + തെറ്റായ രഹസ്യവാക്ക് + InhibitWarnView - Cancel റദ്ദാക്കുക + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - തെറ്റായ രഹസ്യവാക്ക് - MultiUsersWarningView - Cancel റദ്ദാക്കുക - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down നിർത്തുക - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - രഹസ്യവാക്ക് + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + നിർത്തുക + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_mn.ts b/translations/dde-session-shell_mn.ts index f24c813b..729f403c 100644 --- a/translations/dde-session-shell_mn.ts +++ b/translations/dde-session-shell_mn.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Унтраах + Verify your fingerprint + - - - - - Reboot - Дахин ачааллах + Verification successful + - - - - Suspend - Түр зогсоох + + Verification failed, %n chances left + - - - Hibernate - Амраах + Verification failed, only one chance left + - - - - Log out - Гарах + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - Түгжих + Verify your Iris ID + - - Switch user - Хэрэглэгч солих + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + - - Verify your fingerprint or password + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Нууц үг буруу байна - - The domain account or password is not correct. Please enter again. - Домэйн хаяг эсвэл нууц үг буруу байна. Дахин оруулна уу. + Password + Нууц үг + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Бүртгэл + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Нууц үг буруу байна InhibitWarnView - Cancel Цуцлах + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - Домэйн бүртгэл - - - Fingerprint verification timed out, please enter your password manually Хурууны хээ баталгаажуулах цаг дууслаа, гараар нууц үгээ оруулна уу - Failed to match fingerprint Хурууны хээ таарахгүй байна - - - Wrong Password - Нууц үг буруу байна - MultiUsersWarningView - Cancel Цуцлах - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Унтраах - - Reboot Дахин ачааллах - - Suspend Түр зогсоох - - Hibernate Амраах + + Lock + Түгжих + + + Log out + Гарах + + + Switch user + Хэрэглэгч солих + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Системийн хяналтыг эхлүүлэх - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - Нууц үгээ дахин оруулах + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return - - Please repeat the new password + Please select the account for login - - Passwords do not match + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - Нууц үг + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account - Бүртгэл + To close the program, click Cancel, and then close the program. + - - Enter your password to reboot - Дахин ачааллахын тулд нууц үгээ оруулна уу + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Унтраах + + + Reboot + Дахин ачааллах + + + Suspend + Түр зогсоох + + + Hibernate + Амраах + + + Log out + Гарах + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_mr.ts b/translations/dde-session-shell_mr.ts index f5627204..5b781de1 100644 --- a/translations/dde-session-shell_mr.ts +++ b/translations/dde-session-shell_mr.ts @@ -1,222 +1,498 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down / hibernation, and forcing shut down / hibernate may cause data loss. + Face ID - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - - - - Shut down + Verification failed, only one chance left - - - - - Reboot + Verify your Face ID - - - Suspend + Face ID locked, use password please - - - Hibernate + Device unavailable! + + + AuthFingerprint - - - - Log out + Verify your fingerprint - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Fingerprint locked, use password please + + + AuthIris - - Lock + Iris ID - - Switch user + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please - GreeterWorkek + AuthPasskey - - Domain account + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left - Wrong Password - - The domain account or password is not correct. Please enter again. + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password InhibitWarnView - Cancel + + The reason of inhibit. + + - LockWorker + LighterGreeter - - Domain account + Standard Mode + + + LockContent - - Fingerprint verification timed out, please enter your password manually + Lock Screen - - Failed to match fingerprint + Failed to lock screen + + + LockWorker - - Wrong Password + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint MultiUsersWarningView - Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - ShutdownWidget + SessionWidget - - - Shut down + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - - Log in + Shut down - - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - TimeWidget + UdcpMFALoginWidget - - hh:mm - hh:mm + 发送验证码 + - - hh:mm ap + 请输入手机号 - - yyyy-MM-dd dddd - yyyy-MM-dd dddd + 请输入验证码 + + + + 获取验证码 + - UserInputWidget + UpdateWorker - - Log in + Update - - - Please try again %n minute(s) later - + + Please plug in and then install updates. + - UserLoginWidget - - - Please try again %n minute(s) later - + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ms.ts b/translations/dde-session-shell_ms.ts index 1ae3acd2..1c8c5937 100644 --- a/translations/dde-session-shell_ms.ts +++ b/translations/dde-session-shell_ms.ts @@ -1,9 +1,9 @@ - + - AuthFingerprint + AuthFace - Verify your fingerprint - Sahkan cap jari anda + Face ID + Verification successful @@ -11,99 +11,103 @@ Verification failed, %n chances left - Pengesahan gagal, %n peluang berbaki + Verification failed, only one chance left Pengesahan gagal, hanya satu peluang berbaki - Fingerprint locked, use password please - Cap jari dikunci, sila guna kata laluan + Verify your Face ID + - - Please try again %n minute(s) later - Cuba sekali lagi selepas %n minit + + Face ID locked, use password please + + + + Device unavailable! + - AuthPassword + AuthFingerprint + + Verify your fingerprint + Sahkan cap jari anda + Verification successful Pengesahan berjaya Verification failed, %n chances left - Pengesahan gagal, %n peluang berbaki + Verification failed, only one chance left Pengesahan gagal, hanya satu peluang berbaki - Wrong Password - Kata Laluan Salah - - - Password - Kata Laluan - - - Please try again %n minute(s) later - Cuba sekali lagi selepas %n minit + Fingerprint locked, use password please + Cap jari dikunci, sila guna kata laluan - AuthSingle + AuthIris - Please try again 1 minute later - Cuba sekali lagi selepas 1 minit - - - Please try again %n minutes later - Cuba sekali lagi %d minit kemudian + Iris ID + - - - AuthUKey Verification successful Pengesahan berjaya Verification failed, %n chances left - Pengesahan gagal, %n peluang berbaki + Verification failed, only one chance left Pengesahan gagal, hanya satu peluang berbaki - Wrong PIN - PIN salah + Verify your Iris ID + - UKey is required - UKey diperlukan + Iris ID locked, use password please + + + + AuthPasskey - Enter your PIN - Masukkan PIN anda + Please plug in the security key + - - Please try again %n minute(s) later - Cuba sekali lagi %n minit kemudian + + Verification successful + + + + Verification failed + + + + Identifying the security key + - AuthenticationModule + AuthPassword Verification successful Pengesahan berjaya Verification failed, %n chances left - Pengesahan gagal, %n peluang berbaki + Verification failed, only one chance left @@ -114,111 +118,116 @@ Kata Laluan Salah - Wrong PIN - PIN Salah - - - UKey is required - UKey diperlukan + Password + Kata Laluan - Verify your fingerprint - Sahkan cap jari anda + Please try again 1 minute later + Cuba sekali lagi selepas 1 minit - - Password - Kata Laluan + + Please try again %n minutes later + - Enter your PIN - Masukkan PIN anda + Reset Password + - Fingerprint locked, use password please - Cap jari dikunci, sila guna kata laluan + Forgot password? + + + + AuthSingle Please try again 1 minute later Cuba sekali lagi selepas 1 minit Please try again %n minutes later - Cuba sekali lagi %d minit kemudian + - - - ContentWidget - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Ada program yang menghalang komputer dimatikan, dan memaksa dimatikan `boleh menyebabkan kehilangan data. + Reset Password + - To close the program, click Cancel, and then close the program. - Untuk menutup program, klik Batal, kemudian tutup program tersebut. + Forgot password? + + + + AuthUKey - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Ada program yang menghalang komputer dibut semula, dan memaksa but semula`boleh menyebabkan kehilangan data. + Verification successful + Pengesahan berjaya - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Ada program yang menghalang komputer ditangguh, dan memaksa penangguhan`boleh menyebabkan kehilangan data. + + Verification failed, %n chances left + - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Ada program yang menghalang komputer dihibernasikan, dan memaksa dihibernasikan boleh menyebabkan kehilangan data. + Verification failed, only one chance left + Pengesahan gagal, hanya satu peluang berbaki - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Ada program yang menghalang komputer didaftar keluar, dan memaksa daftar keluar`boleh menyebabkan kehilangan data. + Wrong PIN + PIN salah - Shut down - Matikan + UKey is required + UKey diperlukan - Reboot - But semula + Enter your PIN + Masukkan PIN anda - - Suspend - Tangguh + + Please try again %n minute(s) later + - Hibernate - Hibernasi + Please try again 1 minute later + Cuba sekali lagi selepas 1 minit - - Log out - Daftar keluar + + Please try again %n minutes later + + + + AuthWidget - Are you sure you want to shut down? - Anda pasti mahu matikan komputer? + Account + Akaun - - Are you sure you want to reboot? - Anda pasti mahu but semula komputer? + + Your password will expire in %n days, please change it timely + - Are you sure you want to log out? - Anda pasti mahu mendaftar keluar komputer? + Password expired, please change + Kata laluan telah luput, sila ubah - Lock - Kunci + Your password has expired. Please contact the administrator to change it + - Switch user - Tukar pengguna + Terminal locked, please contact administrator + + + + DeepinAuthFramework - Switch system - Tukar sistem + Wrong Password + - GreeterWorkek + GreeterWorker Wrong account Akaun salah @@ -234,6 +243,17 @@ Cancel Batal + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent @@ -272,6 +292,13 @@ Pengguna di atas masih boleh mendaftar masuk dan data tidak akan hilang disebabkan proses but semula komputer, anda pasti mahu but semula komputer? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget @@ -306,6 +333,14 @@ Switch system Tukar sistem + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor @@ -315,22 +350,52 @@ - UserLoginWidget + UdcpMFALoginWidget - Account - Akaun + 发送验证码 + - Verify your fingerprint - Sahkan cap jari anda + 请输入手机号 + - - Your password will expire in %n days, please change it timely - Kata laluan anda akan luput dalam tempoh %d hari, sila ubah ia secepat mungkin + + 请输入验证码 + - Password expired, please change - Kata laluan telah luput, sila ubah + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + @@ -391,5 +456,43 @@ Are you sure you want to log out? Anda pasti mahu mendaftar keluar komputer? + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Hidupkan + + + Turn off + Matikan + \ No newline at end of file diff --git a/translations/dde-session-shell_nb.ts b/translations/dde-session-shell_nb.ts index 1364bfe8..bf646df7 100644 --- a/translations/dde-session-shell_nb.ts +++ b/translations/dde-session-shell_nb.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Slå av + Verify your fingerprint + - - - - - Reboot - Omstart + Verification successful + - - - - Suspend - Suspendere + + Verification failed, %n chances left + - - - Hibernate - Dvale + Verification failed, only one chance left + - - - - Log out - Logg ut + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - Er du sikker på at du vil slå av? + Iris ID + - - Are you sure you want to reboot? - Er du sikker på at du vil omstarte? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - Er du sikker på at du vil logge ut? + Verification failed, only one chance left + - - Lock - Lås + Verify your Iris ID + - - Switch user - Bytt bruker + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password - Bekreft fingeravtrykk eller passord + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Feil passord - - The domain account or password is not correct. Please enter again. + Password + Passord + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + Wrong Password + Feil passord + InhibitWarnView - Cancel Avbryt + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - Domenekonto - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint Fingeravtrykk stemmer ikke. - - - Wrong Password - Feil passord - MultiUsersWarningView - Cancel Avbryt - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Slå av - - Reboot Omstart - - Suspend Suspendere - - Hibernate Dvale + + Lock + Lås + + + Log out + Logg ut + + + Switch user + Bytt bruker + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password - Gjenta passord + Update + - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password - Vennligst oppgi det nye passordet + Please select the account for login + - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Passord + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Skriv inn passord for å starte på nytt. + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Slå av + + + Reboot + Omstart + + + Suspend + Suspendere + + + Hibernate + Dvale + + + Log out + Logg ut + + + Are you sure you want to shut down? + Er du sikker på at du vil slå av? + + + Are you sure you want to reboot? + Er du sikker på at du vil omstarte? + + + Are you sure you want to log out? + Er du sikker på at du vil logge ut? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ne.ts b/translations/dde-session-shell_ne.ts index 70d738ac..68f40376 100644 --- a/translations/dde-session-shell_ne.ts +++ b/translations/dde-session-shell_ne.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - बन्द गर्नुहोस् + Verify your fingerprint + - - - - - Reboot - रिबुट गर्नुहोस् + Verification successful + + + + Verification failed, %n chances left + - - - Suspend - निलम्बन गर्नुहोस् + Verification failed, only one chance left + - - - Hibernate - हाइबर्नेट + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - बाहिर निस्कनुहोस् + Iris ID + - - Are you sure you want to shut down? + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left - - Are you sure you want to reboot? + Verify your Iris ID - - Are you sure you want to log out? + Iris ID locked, use password please + + + AuthPasskey - - Lock - लक + Please plug in the security key + - - Switch user + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + पासवर्ड + - - Verify your fingerprint or password + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + खाता + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker + + Wrong account + + - - The domain account or password is not correct. Please enter again. + Wrong Password InhibitWarnView - Cancel रद्द गर्नुहोस् + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel रद्द गर्नुहोस् - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down बन्द गर्नुहोस् - - Reboot रिबुट गर्नुहोस् - - Suspend निलम्बन गर्नुहोस् - - Hibernate हाइबर्नेट + + Lock + लक + + + Log out + बाहिर निस्कनुहोस् + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password - पासवर्ड फेरि दोहोर्याउँनुहोस् + 请输入验证码 + - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password + Please plug in and then install updates. + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match - गोप्य शब्द मिलेन + Please select the account for login + + + + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - पासवर्ड + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account - खाता + To close the program, click Cancel, and then close the program. + - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + बन्द गर्नुहोस् + + + Reboot + रिबुट गर्नुहोस् + + + Suspend + निलम्बन गर्नुहोस् + + + Hibernate + हाइबर्नेट + + + Log out + बाहिर निस्कनुहोस् + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_nl.ts b/translations/dde-session-shell_nl.ts index e05ef96f..a00a4f4f 100644 --- a/translations/dde-session-shell_nl.ts +++ b/translations/dde-session-shell_nl.ts @@ -27,7 +27,7 @@ Device unavailable! - + Apparaat niet beschikbaar! @@ -80,6 +80,25 @@ Iris ID is vergrendeld - voer je wachtwoord in + + AuthPasskey + + Please plug in the security key + Plug de beveiligingssleutel in + + + Verification successful + Verificatie gelukt + + + Verification failed + Verificatie mislukt + + + Identifying the security key + Bezig met identificeren van sleutel… + + AuthPassword @@ -166,7 +185,7 @@ Please try again %n minute(s) later - Probeer het over %n minuut opnieuwProbeer het over %n minuten opnieuw + Probeer het over %n minuutProbeer het over %n minuten opnieuw Please try again 1 minute later @@ -191,6 +210,21 @@ Password expired, please change Je wachtwoord is verlopen - wijzig het + + Your password has expired. Please contact the administrator to change it + Je wachtwoord is verlopen. Neem contact op met de beheerder om het te wijzigen. + + + Terminal locked, please contact administrator + De terminal is vergrendeld - neem contact op met de systeembeheerder + + + + DeepinAuthFramework + + Wrong Password + Het wachtwoord is onjuist + GreeterWorker @@ -209,6 +243,17 @@ Cancel Annuleren + + The reason of inhibit. + De afsluitreden. + + + + LighterGreeter + + Standard Mode + Standaardmodus + LockContent @@ -225,7 +270,7 @@ LockWorker Fingerprint verification timed out, please enter your password manually - Vingerafdrukauthenticatie verlopen - voer je wachtwoord handmatig in + De vingerafdrukverificatie is verlopen. Voer je wachtwoord handmatig in. Failed to match fingerprint @@ -288,6 +333,14 @@ Switch system Ander systeem + + Update and Shut Down + Bijwerken en afsluiten + + + Update and Reboot + Bijwerken en herstarten + SystemMonitor @@ -296,6 +349,55 @@ Systeemmonitor openen + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + Bijwerken + + + Please plug in and then install updates. + Sluit de netstroomadapter aan alvorens de updates te installeren. + + + + UsersWithTheSameName + + Return + Terug + + + Please select the account for login + Kies het account waarop je wilt inloggen + + + Local Account + Lokaal account + + + Domain Account + Domeinaccount + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Weet je zeker dat je wilt afmelden? + + Update and Shut Down + Bijwerken en afsluiten + + + Update and Reboot + Bijwerken en herstarten + + + Closing the programs and shutting down, please wait... + Bezig met afsluiten van programma's en computer… + + + Closing the programs and rebooting, please wait... + Bezig met afsluiten van programma's en opnieuw opstarten… + + + Closing the programs and logging out, please wait... + Bezig met afsluiten van programma's en uitloggen… + + + + dss::module::AssistLoginWidget + + Automatic login + Automatisch aanmelden + dss::module::NetworkModule diff --git a/translations/dde-session-shell_pa.ts b/translations/dde-session-shell_pa.ts index 03d59d60..c558a4dd 100644 --- a/translations/dde-session-shell_pa.ts +++ b/translations/dde-session-shell_pa.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - ਬੰਦ ਕਰੋ + Verify your fingerprint + - - - - - Reboot - ਮੁੜ-ਚਾਲੂ ਕਰੋ + Verification successful + - - - - Suspend - ਸਸਪੈਂਡ ਕਰੋ + + Verification failed, %n chances left + - - - Hibernate - ਹਾਈਬਰਨੇਟ + Verification failed, only one chance left + - - - - Log out - ਲਾਗ ਆਉਟ ਕਰੋ + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - ਕੀ ਤੁਸੀਂ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + Iris ID + - - Are you sure you want to reboot? - ਕੀ ਤੁਸੀਂ ਮੁੜ-ਚਾਲੂ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - ਕੀ ਤੁਸੀਂ ਲਾਗ ਆਉਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + Verification failed, only one chance left + - - Lock - ਲਾਕ ਕਰੋ + Verify your Iris ID + - - Switch user - ਵਰਤੋਂਕਾਰ ਬਦਲੋ + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password ਗਲਤ ਪਾਸਵਰਡ - - The domain account or password is not correct. Please enter again. + Password + ਪਾਸਵਰਡ + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + ਗਲਤ ਪਾਸਵਰਡ + + InhibitWarnView - Cancel ਰੱਦ ਕਰੋ + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - ਗਲਤ ਪਾਸਵਰਡ - MultiUsersWarningView - Cancel ਰੱਦ ਕਰੋ - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down ਬੰਦ ਕਰੋ - - Reboot ਮੁੜ-ਚਾਲੂ ਕਰੋ - - Suspend ਸਸਪੈਂਡ ਕਰੋ - - Hibernate ਹਾਈਬਰਨੇਟ + + Lock + ਲਾਕ ਕਰੋ + + + Log out + ਲਾਗ ਆਉਟ ਕਰੋ + + + Switch user + ਵਰਤੋਂਕਾਰ ਬਦਲੋ + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor ਸਿਸਟਮ ਨਿਗਰਾਨ ਸ਼ੁਰੂ ਕਰੋ - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password + Please plug in and then install updates. + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match + Please select the account for login + + + + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - ਪਾਸਵਰਡ + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - ਮੁੜ-ਚਾਲੂ ਕਰਨ ਲਈ ਆਪਣਾ ਪਾਸਵਰਡ ਦਿਓ + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down - ਬੰਦ ਕਰਨ ਲਈ ਆਪਣਾ ਪਾਸਵਰਡ ਦਿਓ + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + ਬੰਦ ਕਰੋ + + + Reboot + ਮੁੜ-ਚਾਲੂ ਕਰੋ + + + Suspend + ਸਸਪੈਂਡ ਕਰੋ + + + Hibernate + ਹਾਈਬਰਨੇਟ + + + Log out + ਲਾਗ ਆਉਟ ਕਰੋ + + + Are you sure you want to shut down? + ਕੀ ਤੁਸੀਂ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + + + Are you sure you want to reboot? + ਕੀ ਤੁਸੀਂ ਮੁੜ-ਚਾਲੂ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + + + Are you sure you want to log out? + ਕੀ ਤੁਸੀਂ ਲਾਗ ਆਉਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_pam.ts b/translations/dde-session-shell_pam.ts index 376a84f8..08242d1e 100644 --- a/translations/dde-session-shell_pam.ts +++ b/translations/dde-session-shell_pam.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down + Verify your fingerprint - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword - - Verify your fingerprint or password + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Pasword + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? - GreeterWorkek + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel I-cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel I-cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Pasword + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to reboot + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the account + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - Please enter the password + Shut down - - - Please try again %n minute(s) later - + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_pl.ts b/translations/dde-session-shell_pl.ts index 2bda50c2..c60e691a 100644 --- a/translations/dde-session-shell_pl.ts +++ b/translations/dde-session-shell_pl.ts @@ -11,11 +11,11 @@ Verification failed, %n chances left - Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n prób Weryfikacja nie powiodła się, pozostało %n prób + Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n próbWeryfikacja nie powiodła się, pozostało %n prób Verification failed, only one chance left - Weryfikacja nie powiodła się, pozostała tylko jedna szansa + Weryfikacja nie powiodła się, pozostała tylko jedna próba Verify your Face ID @@ -23,18 +23,18 @@ Face ID locked, use password please - ID Twarzy zablokowane, proszę użyć hasła + ID Twarzy zablokowane, użyj hasła Device unavailable! - + Urządzenie niedostępne! AuthFingerprint Verify your fingerprint - Zweryfikuj odcisk palca + Zweryfikuj odcisk palca Verification successful @@ -42,11 +42,11 @@ Verification failed, %n chances left - Weryfikacja nie powiodła się, pozostała %n próba Weryfikacja nie powiodła się, pozostały %n próby Weryfikacja nie powiodła się, pozostało %n prób Weryfikacja nie powiodła się, pozostało %n prób + Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n próbWeryfikacja nie powiodła się, pozostało %n prób Verification failed, only one chance left - Weryfikacja nie powiodła się, pozostała tylko jedna szansa + Weryfikacja nie powiodła się, pozostała tylko jedna próba Fingerprint locked, use password please @@ -65,11 +65,11 @@ Verification failed, %n chances left - Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n prób Weryfikacja nie powiodła się, pozostało %n prób + Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n próbWeryfikacja nie powiodła się, pozostało %n prób Verification failed, only one chance left - Weryfikacja nie powiodła się, pozostała tylko jedna szansa + Weryfikacja nie powiodła się, pozostała tylko jedna próba Verify your Iris ID @@ -77,7 +77,26 @@ Iris ID locked, use password please - ID Tęczówki zablokowane, proszę użyć hasła + ID Tęczówki zablokowane, użyj hasła + + + + AuthPasskey + + Please plug in the security key + Podłącz klucz bezpieczeństwa + + + Verification successful + Weryfikacja zakończona pomyślnie + + + Verification failed + Weryfikacja nie powiodła się + + + Identifying the security key + Identyfikuję klucz bezpieczeństwa @@ -88,15 +107,15 @@ Verification failed, %n chances left - Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n prób Weryfikacja nie powiodła się, pozostało %n prób + Weryfikacja nie powiodła się, pozostała %n próbaWeryfikacja nie powiodła się, pozostały %n próbyWeryfikacja nie powiodła się, pozostało %n próbWeryfikacja nie powiodła się, pozostało %n prób Verification failed, only one chance left - Weryfikacja nie powiodła się, pozostała tylko jedna szansa + Weryfikacja nie powiodła się, pozostała tylko jedna próba Wrong Password - Nieprawidłowe hasło + Błędne hasło Password @@ -108,7 +127,7 @@ Please try again %n minutes later - Spróbuj ponownie za %n minuteSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut + Spróbuj ponownie za %n minutęSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut Reset Password @@ -127,7 +146,7 @@ Please try again %n minutes later - Spróbuj ponownie za %n minuteSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut + Spróbuj ponownie za %n minutęSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut Reset Password @@ -150,11 +169,11 @@ Verification failed, only one chance left - Weryfikacja nie powiodła się, pozostała tylko jedna szansa + Weryfikacja nie powiodła się, pozostała tylko jedna próba Wrong PIN - Nieprawidłowy PIN + Błędny PIN UKey is required @@ -162,11 +181,11 @@ Enter your PIN - Wpisz swój PIN + Wprowadź swój PIN Please try again %n minute(s) later - Spróbuj ponownie za %n minuteSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut + Spróbuj ponownie za %n minutęSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut Please try again 1 minute later @@ -174,7 +193,7 @@ Please try again %n minutes later - Spróbuj ponownie za %n minuteSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut + Spróbuj ponownie za %n minutęSpróbuj ponownie za %n minutySpróbuj ponownie za %n minutSpróbuj ponownie za %n minut @@ -191,6 +210,21 @@ Password expired, please change Hasło wygasło, proszę zmień je + + Your password has expired. Please contact the administrator to change it + Twoje hasło wygasło. Skontaktuj się z administratorem, aby je zmienić. + + + Terminal locked, please contact administrator + Terminal został zablokowany, skontaktuj się z administratorem + + + + DeepinAuthFramework + + Wrong Password + Błędne hasło + GreeterWorker @@ -200,7 +234,7 @@ Wrong Password - Nieprawidłowe Hasło + Błędne hasło @@ -209,12 +243,23 @@ Cancel Anuluj + + The reason of inhibit. + Powód wstrzymania. + + + + LighterGreeter + + Standard Mode + Tryb standardowy + LockContent Lock Screen - Zablokuj ekran + Ekran blokady Failed to lock screen @@ -229,7 +274,7 @@ Failed to match fingerprint - Błąd porównania odcisków palcy + Nie udało się zweryfikować odcisku palca @@ -240,18 +285,18 @@ The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - Powyżsi użytkownicy są wciąż zalogowani i ich dane mogą zostać utracone w wyniku wyłączenia komputera. Czy na pewno wyłączyć komputer? + Powyżsi użytkownicy są wciąż zalogowani, a ich dane mogą zostać utracone poprzez wyłączenie. Czy na pewno wyłączyć? The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - Powyżsi użytkownicy są wciąż zalogowani i ich dane mogą zostać utracone w wyniku ponownego uruchomienia komputera. Czy na pewno chcesz ponownie uruchomić komputer? + Powyżsi użytkownicy są wciąż zalogowani, a ich dane mogą zostać utracone poprzez ponowne uruchomienie. Czy na pewno uruchomić ponownie? SessionWidget You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. - Wysoki poziom został włączony, z tego powodu nie jesteś w stanie przełączyć się na sesję Wayland. Wyłącz wysoki poziom zabezpieczeń w Centrum Bezpieczeństwa, a następnie spróbuj ponownie. + Wysoki poziom bezpieczeństwa jest aktywny, więc nie można przełączyć na sesję Wayland. Wyłącz wysoki poziom bezpieczeństwa w Centrum Bezpieczeństwa, a następnie spróbuj ponownie. @@ -288,6 +333,14 @@ Switch system System przełączników + + Update and Shut Down + Aktualizuj i zamknij + + + Update and Reboot + Aktualizuj i uruchom ponownie + SystemMonitor @@ -296,6 +349,55 @@ Uruchom monitor systemu + + UdcpMFALoginWidget + + 发送验证码 + CAPTCHA + + + 请输入手机号 + Wprowadź numer telefonu + + + 请输入验证码 + Wprowadź kod weryfikacyjny + + + 获取验证码 + Pobierz CAPTCHA + + + + UpdateWorker + + Update + Aktualizuj + + + Please plug in and then install updates. + Najpierw podłącz się do zasilania, aby zainstalować aktualizacje. + + + + UsersWithTheSameName + + Return + Wróć + + + Please select the account for login + Wybierz konto do zalogowania + + + Local Account + Konto lokalne + + + Domain Account + Konto domeny + + WarningContent @@ -324,7 +426,7 @@ Shut down - Zamknij + Wyłącz Reboot @@ -336,7 +438,7 @@ Hibernate - Hibernować + Hibernacja Log out @@ -344,16 +446,43 @@ Are you sure you want to shut down? - Czy na pewno chcesz zamknąć? + Czy na pewno chcesz wyłączyć? Are you sure you want to reboot? - Czy na pewno chcesz uruchomić ponownie komputer? + Czy na pewno chcesz uruchomić ponownie? Are you sure you want to log out? Czy na pewno chcesz się wylogować? + + Update and Shut Down + Aktualizuj i zamknij + + + Update and Reboot + Aktualizuj i uruchom ponownie + + + Closing the programs and shutting down, please wait... + Zamykanie programów i wyłączanie, proszę czekać... + + + Closing the programs and rebooting, please wait... + Zamykanie programów i uruchamianie ponowne, proszę czekać... + + + Closing the programs and logging out, please wait... + Zamykanie programów i wylogowywanie, proszę czekać... + + + + dss::module::AssistLoginWidget + + Automatic login + Automatyczne logowanie + dss::module::NetworkModule diff --git a/translations/dde-session-shell_ps.ts b/translations/dde-session-shell_ps.ts new file mode 100644 index 00000000..bb693cdc --- /dev/null +++ b/translations/dde-session-shell_ps.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_pt.ts b/translations/dde-session-shell_pt.ts index 73fa9bd9..ba86a0ac 100644 --- a/translations/dde-session-shell_pt.ts +++ b/translations/dde-session-shell_pt.ts @@ -11,7 +11,7 @@ Verification failed, %n chances left - Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes + Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes Verification failed, only one chance left @@ -27,7 +27,7 @@ Device unavailable! - + Dispositivo indisponível! @@ -42,7 +42,7 @@ Verification failed, %n chances left - Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes + Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantesFalha ao verificar, %n tentativas restantes Verification failed, only one chance left @@ -65,7 +65,7 @@ Verification failed, %n chances left - Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes + Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantesFalha ao verificar, %n tentativas restantes Verification failed, only one chance left @@ -80,6 +80,25 @@ ID da íris bloqueada, usar a palavra-passe + + AuthPasskey + + Please plug in the security key + Por favor introduza a chave de segurança + + + Verification successful + Verificação bem sucedida + + + Verification failed + Verificação falhada + + + Identifying the security key + A identificar a chave de segurança + + AuthPassword @@ -88,7 +107,7 @@ Verification failed, %n chances left - Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes + Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantesFalha ao verificar, %n tentativas restantes Verification failed, only one chance left @@ -108,7 +127,7 @@ Please try again %n minutes later - Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tarde + Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tardeTentar novamente %n minutos mais tarde Reset Password @@ -127,7 +146,7 @@ Please try again %n minutes later - Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tarde + Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tardeTentar novamente %n minutos mais tarde Reset Password @@ -146,7 +165,7 @@ Verification failed, %n chances left - Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantes + Falha ao verificar, %n tentativa restanteFalha ao verificar, %n tentativas restantesFalha ao verificar, %n tentativas restantes Verification failed, only one chance left @@ -166,7 +185,7 @@ Please try again %n minute(s) later - Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tarde + Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tardeTentar novamente %n minutos mais tarde Please try again 1 minute later @@ -174,7 +193,7 @@ Please try again %n minutes later - Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tarde + Tentar novamente %n minuto mais tardeTentar novamente %n minutos mais tardeTentar novamente %n minutos mais tarde @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - A palavra-passe expirará dentro de %n dia. Altere-a atempadamenteA palavra-passe expirará dentro de %n dias. Altere-a atempadamente + A sua palavra-passe expirará dentro de %n dias, por favor altere-a atempadamenteA sua palavra-passe expirará dentro de %n dias. Altere-a atempadamenteA sua palavra-passe vai expirar dentro de %1 dias. Por favor altere-a atempadamente. Password expired, please change A palavra-passe expirou, altere-a + + Your password has expired. Please contact the administrator to change it + A sua palavra-passe expirou. Por favor contacte o administrador para a alterar + + + Terminal locked, please contact administrator + Terminal trancado, por favor contacte o administrador + + + + DeepinAuthFramework + + Wrong Password + Palavra-passe Errada + GreeterWorker @@ -209,6 +243,17 @@ Cancel Cancelar + + The reason of inhibit. + A razão da inibição + + + + LighterGreeter + + Standard Mode + Modo Padrão + LockContent @@ -218,14 +263,14 @@ Failed to lock screen - O bloqueio do ecrã falhou + Falha ao bloquear o ecrã LockWorker Fingerprint verification timed out, please enter your password manually - A verificação da impressão digital expirou, insira manualmente a sua palavra-passe + A verificação da impressão digital expirou, introduza manualmente a sua palavra-passe Failed to match fingerprint @@ -251,7 +296,7 @@ SessionWidget You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. - Ativou o modo de alta segurança no sistema, impedindo de alterar para o modo Wayland. Por favor desative o modo de alta segurança no Centro de Segurança e tente novamente. + Ativou o modo de alta segurança no sistema, não podendo assim mudar para o modo Wayland. Desative o modo de alta segurança no Centro de Segurança e tente novamente. @@ -288,6 +333,14 @@ Switch system Mudar de sistema + + Update and Shut Down + Atualizar e Encerrar + + + Update and Reboot + Atualizar e Reiniciar + SystemMonitor @@ -296,6 +349,55 @@ Iniciar monitor do sistema + + UdcpMFALoginWidget + + 发送验证码 + Enviar código de verificação + + + 请输入手机号 + Introduza o número de telemóvel + + + 请输入验证码 + Introduza o código de verificação + + + 获取验证码 + Obter código de verificação + + + + UpdateWorker + + Update + Atualizar + + + Please plug in and then install updates. + Por favor insira e depois instale atualizações. + + + + UsersWithTheSameName + + Return + Voltar + + + Please select the account for login + Por favor selecione a conta para início de sessão + + + Local Account + Conta Local + + + Domain Account + Conta de Domínio + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Tem a certeza que deseja terminar a sessão? + + Update and Shut Down + Atualizar e Encerrar + + + Update and Reboot + Atualizar e Reiniciar + + + Closing the programs and shutting down, please wait... + A fechar os programas e a encerrar, por favor aguarde... + + + Closing the programs and rebooting, please wait... + A fechar os programas e a reiniciar, por favor aguarde... + + + Closing the programs and logging out, please wait... + A fechar os programas a sair da sessão, por favor aguarde... + + + + dss::module::AssistLoginWidget + + Automatic login + Início de sessão automático + dss::module::NetworkModule diff --git a/translations/dde-session-shell_pt_BR.ts b/translations/dde-session-shell_pt_BR.ts index 50231b2a..12b12bc8 100644 --- a/translations/dde-session-shell_pt_BR.ts +++ b/translations/dde-session-shell_pt_BR.ts @@ -1,9 +1,9 @@ - + - AuthFingerprint + AuthFace - Verify your fingerprint - Verifique a impressão digital + Face ID + Face ID Verification successful @@ -11,214 +11,223 @@ Verification failed, %n chances left - A verificação falhou; restam %n tentativasA verificação falhou; restam %n tentativas + A verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantes Verification failed, only one chance left - A verificação falhou; resta apenas uma tentativa + A verificação falhou, apenas uma tentativa restante - Fingerprint locked, use password please - Impressão digital bloqueada; utilize a senha + Verify your Face ID + Verifique seu Face ID - - Please try again %n minute(s) later - Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) + + Face ID locked, use password please + Face ID bloqueado, use a senha + + + Device unavailable! + Dispositivo indisponível! - AuthPassword + AuthFingerprint + + Verify your fingerprint + Verifique a impressão digital + Verification successful Verificação bem-sucedida Verification failed, %n chances left - A verificação falhou; restam %n tentativasA verificação falhou; restam %n tentativas + A verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantes Verification failed, only one chance left - A verificação falhou; resta apenas uma tentativa - - - Wrong Password - Senha Incorreta + A verificação falhou, apenas uma tentativa restante - Password - Senha - - - Please try again %n minute(s) later - Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) + Fingerprint locked, use password please + Impressão digital bloqueada; utilize a senha - AuthSingle + AuthIris - Please try again 1 minute later - Tente novamente em 1 minuto + Iris ID + Íris ID - - Please try again %n minutes later - Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) - - - - AuthUKey Verification successful Verificação bem-sucedida Verification failed, %n chances left - A verificação falhou; restam %n tentativasA verificação falhou; restam %n tentativas + A verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantes Verification failed, only one chance left - A verificação falhou; resta apenas uma tentativa + A verificação falhou, apenas uma tentativa restante - Wrong PIN - PIN incorreto + Verify your Iris ID + Verifique sua Íris ID - UKey is required - A UKey é necessária + Iris ID locked, use password please + Íris ID bloqueado, use a senha + + + AuthPasskey - Enter your PIN - Insira o PIN + Please plug in the security key + Conecte a chave de segurança - - Please try again %n minute(s) later - Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) + + Verification successful + Verificação bem-sucedida + + + Verification failed + A verificação falhou + + + Identifying the security key + Identificando chave de segurança - AuthenticationModule + AuthPassword Verification successful Verificação bem-sucedida Verification failed, %n chances left - A verificação falhou; restam %n tentativasA verificação falhou; restam %n tentativas + A verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantes Verification failed, only one chance left - A verificação falhou; resta apenas uma tentativa + A verificação falhou, apenas uma tentativa restante Wrong Password Senha Incorreta - Wrong PIN - PIN incorreto - - - UKey is required - A UKey é necessária + Password + Senha - Verify your fingerprint - Verifique a impressão digital + Please try again 1 minute later + Tente novamente em 1 minuto - - Password - Senha + + Please try again %n minutes later + Tente novamente em %n minuto(s)Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) - Enter your PIN - Insira o PIN + Reset Password + Redefinir senha - Fingerprint locked, use password please - Impressão digital bloqueada; utilize a senha + Forgot password? + Esqueceu a senha? + + + AuthSingle Please try again 1 minute later Tente novamente em 1 minuto Please try again %n minutes later - Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) + Tente novamente em %n minuto(s)Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) - - - ContentWidget - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Os processos acima estão impedindo que o computador seja desligado; e forçar o desligamento, poderá causar a perda de dados. + Reset Password + Redefinir senha - To close the program, click Cancel, and then close the program. - Para fechar o programa, clique em Cancelar e feche o programa. + Forgot password? + Esqueceu a senha? + + + AuthUKey - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Os processos acima estão impedindo que o computador seja reiniciado; e forçar a reinicialização, poderá causar a perda de dados. + Verification successful + Verificação bem-sucedida - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Os processos acima estão impedindo que o computador seja suspenso; e forçar a suspensão, poderá causar a perda de dados. + + Verification failed, %n chances left + A verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantesA verificação falhou, %n tentativas restantes - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Os processos acima estão impedindo que o computador seja hibernado; e forçar a hibernação, poderá causar a perda de dados. + Verification failed, only one chance left + A verificação falhou, apenas uma tentativa restante - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Os processos acima estão impedindo que o computador encerre a sessão; e forçar o encerramento da sessão, poderá causar a perda de dados. + Wrong PIN + PIN incorreto - Shut down - Desligar + UKey is required + A UKey é necessária - Reboot - Reiniciar + Enter your PIN + Insira seu PIN - - Suspend - Suspender + + Please try again %n minute(s) later + Tente novamente em %n minuto(s)Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) - Hibernate - Hibernar + Please try again 1 minute later + Tente novamente em 1 minuto - - Log out - Sair + + Please try again %n minutes later + Tente novamente em %n minuto(s)Tente novamente em %n minuto(s)Tente novamente em %n minuto(s) + + + AuthWidget - Are you sure you want to shut down? - Desligar? + Account + Contas - - Are you sure you want to reboot? - Reiniciar? + + Your password will expire in %n days, please change it timely + Sua senha expirará em %n dia, altere-a em tempo hábilSua senha expirará em %n dias, altere-a em tempo hábilSua senha expirará em %n dias, altere-a em tempo hábil - Are you sure you want to log out? - Sair? + Password expired, please change + A senha expirou; altere-a - Lock - Bloquear + Your password has expired. Please contact the administrator to change it + Sua senha expirou. Entre em contato com o administrador para alterá-la - Switch user - Alternar Usuário + Terminal locked, please contact administrator + Terminal bloqueado, entre em contato com o administrador + + + DeepinAuthFramework - Switch system - Alternar Sistema + Wrong Password + Senha Errada - GreeterWorkek + GreeterWorker Wrong account Conta incorreta @@ -234,6 +243,17 @@ Cancel Cancelar + + The reason of inhibit. + O motivo da inibição. + + + + LighterGreeter + + Standard Mode + Modo Padrão + LockContent @@ -250,7 +270,7 @@ LockWorker Fingerprint verification timed out, please enter your password manually - O tempo de verificação da impressão digital expirou; digite a senha + O tempo de verificação da impressão digital expirou, insira sua senha manualmente Failed to match fingerprint @@ -272,6 +292,13 @@ Os usuários acima ainda estão conectados e os dados serão perdidos devido à reinicialização. Reiniciar? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + Você ativou o nível alto de segurança do sistema e, portanto, não pode alternar para o modo Wayland. Desative o nível alto de segurança na Central de Segurança e tente novamente. + + ShutdownWidget @@ -300,37 +327,75 @@ Switch user - Alternar usuário + Trocar usuário Switch system Alternar sistema + + Update and Shut Down + Atualizar e desligar + + + Update and Reboot + Atualizar e reiniciar + SystemMonitor Start system monitor - Monitor de Sistema + Monitor do Sistema - UserLoginWidget + UdcpMFALoginWidget - Account - Conta + 发送验证码 + Enviar código de verificação - Verify your fingerprint - Verifique a impressão digital + 请输入手机号 + Digite o número de telefone - - Your password will expire in %n days, please change it timely - A senha expirará em %n dias; altere-a em tempo hábilA senha expirará em %n dias; altere-a em tempo hábil + + 请输入验证码 + Digite o código de verificação - Password expired, please change - A senha expirou; altere-a + 获取验证码 + Obter código de verificação + + + + UpdateWorker + + Update + Atualizar + + + Please plug in and then install updates. + Conecte o carregador para instalar as atualizações. + + + + UsersWithTheSameName + + Return + Retornar + + + Please select the account for login + Por favor, selecione a conta para logar + + + Local Account + Conta Local + + + Domain Account + Conta de domínio @@ -391,5 +456,43 @@ Are you sure you want to log out? Sair? + + Update and Shut Down + Atualizar e desligar + + + Update and Reboot + Atualizar e reiniciar + + + Closing the programs and shutting down, please wait... + Fechando os programas e desligando, aguarde... + + + Closing the programs and rebooting, please wait... + Fechando os programas e reiniciando, aguarde... + + + Closing the programs and logging out, please wait... + Fechando os programas e saindo, aguarde... + + + + dss::module::AssistLoginWidget + + Automatic login + Login automático + + + + dss::module::NetworkModule + + Turn on + Ativar + + + Turn off + Desativar + \ No newline at end of file diff --git a/translations/dde-session-shell_qu.ts b/translations/dde-session-shell_qu.ts new file mode 100644 index 00000000..ddf09abf --- /dev/null +++ b/translations/dde-session-shell_qu.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ro.ts b/translations/dde-session-shell_ro.ts index a5b8afca..16659543 100644 --- a/translations/dde-session-shell_ro.ts +++ b/translations/dde-session-shell_ro.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Programele împiedică oprirea computerului, forțarea închiderii poate cauza pierderi de date. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Pentru a închide programul, faceți întai click pe Anulare, apoi închide programul. + Verification successful + Verificare reușită + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Programele împiedică repornirea computerului, forțarea repornirii poate cauza pierderi de date. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Programele împiedică suspendarea computerului, forțarea suspendării poate cauza pierderi de date. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Programele împiedică hibernarea computerului, forțarea hibernării poate cauza pierderi de date. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Programele împiedică delogarea computerului, forțarea delogării poate cauza pierderi de date. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Închidere + Verify your fingerprint + - - - - - Reboot - Repornire + Verification successful + Verificare reușită + + + Verification failed, %n chances left + - - - Suspend - Suspendare + Verification failed, only one chance left + - - - Hibernate - Hibernare + Fingerprint locked, use password please + Amprentă digitală blocată, utilizați parolă + + + AuthIris - - - - Log out - Ieșire + Iris ID + - - Are you sure you want to shut down? - Sigur doriți să închideți? + Verification successful + Verificare reușită + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Sigur doriți să reporniți? + Verification failed, only one chance left + - - Are you sure you want to log out? - Sigur doriți să va delogaţi? + Verify your Iris ID + - - Lock - Blocare + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Schimbare utilizator + Please plug in the security key + - - Switch system - Comutare sistem + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + Verificare reușită + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Parolă Incorectă - - The account or password is not correct. Please enter again. - Cont sau parolă incorecte. Vă rugăm reîncercaţi. + Password + Parola + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + Verificare reușită + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Cont + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Parolă expirată, vă rugăm schimbați + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Parolă Incorectă InhibitWarnView - Cancel Anulează + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Blocare ecran - Failed to lock screen Blocarea ecranului eşuată @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Verificarea prin amprentă a expirat, vă rugăm să introduceți o parolă manuală - Failed to match fingerprint Potrivire amprenta eşuată - - - Wrong Password - Parolă Incorectă - MultiUsersWarningView - Cancel Anulează - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Utilizatorii de mai sus sunt încă conectați și datele vor fi pierdute datorită închiderii, sigur doriți să închideţi? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Utilizatorii de mai sus sunt încă conectați și datele vor fi pierdute datorită repornirii, sigur doriți să reporniți? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Închidere - - Reboot Repornire - - Suspend Suspendare - - Hibernate Hibernare + + Lock + Blocare + + + Log out + Ieșire + + + Switch user + Schimbare utilizator + + + Switch system + Comutare sistem + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Pornire monitor sistem - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Parolă expirată, vă rugăm schimbați + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + - - New password - Parolă nouă + 获取验证码 + + + + UpdateWorker - - Repeat password - Reintroduceți parola + Update + - - Failed to change your password - Modificarea parolei a eșuat + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - Parolă prea slabă + Return + - - Please enter the new password - Vă rugăm introduceți noua parolă + Please select the account for login + - - Please repeat the new password - Vă rugăm repetați noua parolă + Local Account + - - Passwords do not match - Noua parolă nu corespunde + Domain Account + - UserLoginWidget + WarningContent - - Password - Parola + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Programele împiedică oprirea computerului, forțarea închiderii poate cauza pierderi de date. - - Account - Cont + To close the program, click Cancel, and then close the program. + Pentru a închide programul, faceți întai click pe Anulare, apoi închide programul. - - Please enter the account - Vă rugăm introduceți contul + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Programele împiedică repornirea computerului, forțarea repornirii poate cauza pierderi de date. - - Please enter the password - Vă rugăm introduceți parola + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Programele împiedică suspendarea computerului, forțarea suspendării poate cauza pierderi de date. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Programele împiedică hibernarea computerului, forțarea hibernării poate cauza pierderi de date. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Programele împiedică delogarea computerului, forțarea delogării poate cauza pierderi de date. + + + Shut down + Închidere + + + Reboot + Repornire + + + Suspend + Suspendare + + + Hibernate + Hibernare + + + Log out + Ieșire + + + Are you sure you want to shut down? + Sigur doriți să închideți? + + + Are you sure you want to reboot? + Sigur doriți să reporniți? + + + Are you sure you want to log out? + Sigur doriți să va delogaţi? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Pornește + + + Turn off + Oprește \ No newline at end of file diff --git a/translations/dde-session-shell_ru.ts b/translations/dde-session-shell_ru.ts index 08e65832..09dd5280 100644 --- a/translations/dde-session-shell_ru.ts +++ b/translations/dde-session-shell_ru.ts @@ -1,319 +1,267 @@ - + - AuthFingerprint + AuthFace - - - Verify your fingerprint - Проверка отпечатка пальца + Face ID + Face ID - Verification successful - Проверка прошла успешно + Успешная проверка - Verification failed, %n chances left - + Проверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %n - Verification failed, only one chance left - Проверка не удалась, у Вас осталась одна попытка + Проверка не удалась, осталась одна попытка - - Fingerprint locked, use password please - Проверка отпечатков пальцев заблокирована, пожалуйста, введите пароль + Verify your Face ID + Подтвердите свой Face ID - - - Please try again %n minute(s) later - + + Face ID locked, use password please + Face ID заблокирован, пожалуйста, используйте пароль + + + Device unavailable! + Устройство недоступно! - AuthPassword + AuthFingerprint + + Verify your fingerprint + Проверка отпечатка пальца + - Verification successful Проверка прошла успешно - Verification failed, %n chances left - + Проверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %n - Verification failed, only one chance left - Проверка не удалась, у Вас осталась одна попытка + Проверка не удалась, осталась одна попытка - - Wrong Password - Неверный Пароль - - - - Password - Пароль - - - - Please try again %n minute(s) later - + Fingerprint locked, use password please + Проверка отпечатков пальцев заблокирована, пожалуйста, введите пароль - AuthSingle - - - Please try again %n minute(s) later - + AuthIris + + Iris ID + Iris ID - - - AuthUKey - Verification successful - Проверка прошла успешно + Успешная проверка - Verification failed, %n chances left - + Проверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %n - Verification failed, only one chance left - Проверка не удалась, у Вас осталась одна попытка + Проверка не удалась, осталась одна попытка - - Wrong PIN - Неверный PIN + Verify your Iris ID + Подтвердите свой Iris ID - - UKey is required - Запрошен UKey + Iris ID locked, use password please + Face ID заблокирован, пожалуйста, используйте пароль + + + AuthPasskey - - Enter your PIN - Введите Ваш PIN + Please plug in the security key + Пожалуйста, подключите ключ безопасности - - - Please try again %n minute(s) later - + + Verification successful + Успешная проверка + + + Verification failed + Проверка не удалась + + + Identifying the security key + Пожалуйста, подключите ключ безопасности - AuthenticationModule - - - - - - Please try again %n minute(s) later - - + AuthPassword - - Verification successful - Проверка прошла успешно + Успешная проверка - - Verification failed, %n chances left - + Проверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %n - - Verification failed, only one chance left - + Проверка не удалась, осталась только одна попытка - Wrong Password - - - - - Wrong PIN - + Неверный пароль - - UKey is required - + Password + Пароль - - Verify your fingerprint - + Please try again 1 minute later + Повторите попытку через 1 минуту - - - Password - + + Please try again %n minutes later + Пожалуйста, повторите через %n мин.Пожалуйста, повторите через %n мин.Пожалуйста, повторите через %n мин.Повторите попытку через %n мин. - - Enter your PIN - + Reset Password + Сброс пароля - - Fingerprint locked, use password please - Отпечатки пальцев заблокированы, пожалуйста, используйте пароль + Forgot password? + Забыли пароль? - ContentWidget + AuthSingle - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Программы предотвращают выключение компьютера, а принудительное выключение может привести к потере данных. + Please try again 1 minute later + Повторите попытку через 1 минуту - - - - - - - To close the program, click Cancel, and then close the program. - Чтобы закрыть программу, нажмите Отмена, и затем закройте программу. + + Please try again %n minutes later + Повторите попытку через %n мин.Повторите попытку через %n мин.Повторите попытку через %n мин.Повторите попытку через %n мин. - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Программы препятствуют перезагрузке компьютера, а принудительная перезагрузка может привести к потере данных. + Reset Password + Сброс пароля - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Программы не позволяют компьютеру приостановить работу, а принудительная приостановка может привести к потере данных. + Forgot password? + Забыли пароль? + + + AuthUKey - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Программы не позволяют компьютеру переходить в спящий режим, а принудительное использование спящего режима может привести к потере данных. + Verification successful + Проверка прошла успешно - - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Программы не позволяют компьютеру выйти из системы, а принудительный выход может привести к потере данных. + + Verification failed, %n chances left + Проверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %nПроверка не удалась, осталось попыток: %n - - - - - Shut down - Выключить + Verification failed, only one chance left + Проверка не удалась, осталась одна попытка - - - - - Reboot - Перезагрузить + Wrong PIN + Неверный PIN - - - Suspend - Приостановить + UKey is required + Запрошен UKey - - - Hibernate - Спящий режим + Enter your PIN + Введите ваш PIN - - - - - Log out - Выйти + + Please try again %n minute(s) later + Пожалуйста, попробуйте снова через %n мин.Пожалуйста, попробуйте снова через %n мин.Пожалуйста, попробуйте снова через %n мин.Пожалуйста, попробуйте снова через %n мин. - - Are you sure you want to shut down? - Вы уверены, что хотите выключить? + Please try again 1 minute later + Повторите попытку через 1 минуту + + + Please try again %n minutes later + Повторите попытку через %n мин.Повторите попытку через %n мин.Повторите попытку через %n мин.Повторите попытку через %n мин. + + + AuthWidget - - Are you sure you want to reboot? - Вы уверены, что хотите перезагрузить? + Account + Учетная запись + + + Your password will expire in %n days, please change it timely + Срок действия вашего пароля истечет через %n д., пожалуйста, своевременно измените егоСрок действия вашего пароля истечет через %n д., пожалуйста, своевременно измените егоСрок действия вашего пароля истечет через %n д., пожалуйста, своевременно измените егоСрок действия вашего пароля истечет через %n д., пожалуйста, своевременно измените его - - Are you sure you want to log out? - Вы уверены, что хотите выйти? + Password expired, please change + Срок действия пароля истек, пожалуйста, измените - - Lock - Блокировать + Your password has expired. Please contact the administrator to change it + Срок действия вашего пароля истек. Пожалуйста, свяжитесь с администратором, чтобы изменить его - - Switch user - Сменить пользователя + Terminal locked, please contact administrator + Терминал заблокирован, пожалуйста, свяжитесь с администратором + + + DeepinAuthFramework - - Switch system - Переключить систему + Wrong Password + Неверный пароль - GreeterWorkek + GreeterWorker - Wrong account - + Неправильный аккаунт - Wrong Password - Неверный Пароль - - - - The account or password is not correct. Please enter again. - учетная запись или пароль введены неверно. Пожалуйста, попробуйте снова + Неверный пароль InhibitWarnView - - Cancel Отмена + + The reason of inhibit. + Причина подавления. + + + + LighterGreeter + + Standard Mode + Обычный режим + LockContent - Lock Screen - Экран Блокировки + Экран блокировки - Failed to lock screen Не удалось заблокировать экран @@ -321,12 +269,10 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Время проверки отпечатка пальца вышло, пожалуйста, введите свой пароль вручную - Failed to match fingerprint Не удалось сопоставить отпечаток пальца @@ -334,179 +280,219 @@ MultiUsersWarningView - - Cancel Отмена - - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Некоторые пользователи по-прежнему находятся в системе и данные будут потеряны после выключения, вы уверены, что хотите выключить? - - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Некоторые пользователи по-прежнему находятся в системе и данные будут потеряны после перезагрузки, вы уверены, что хотите перезагрузить? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + Вы включили высокий уровень безопасности системы, поэтому не можете переключиться в режим Wayland, отключите высокий уровень безопасности в Центре безопасности и повторите попытку. + + ShutdownWidget - Shut down Выключить - - Reboot Перезагрузить - - Suspend Приостановить - - Hibernate Спящий режим - Lock Блокировать - Log out Выйти - Switch user - Сменить пользователя + Переключить пользователя - Switch system Переключить систему + + Update and Shut Down + Обновить и выключить + + + Update and Reboot + Обновить и перезагрузить + SystemMonitor - - Start system monitor Запустить системный монитор - UserLoginWidget + UdcpMFALoginWidget - - - Account - Учетная запись + 发送验证码 + Отправить проверочный код - - - Verify your fingerprint - Проверьте свой отпечаток пальца + 请输入手机号 + Пожалуйста, введите Ваш номер телефона - - - Please try again %n minute(s) later - Пожалуйста попробуйте снова через %n минутуПожалуйста попробуйте снова через %n минутПожалуйста попробуйте снова через %n минутПожалуйста попробуйте снова через %n минут(у) + + 请输入验证码 + Пожалуйста, введите проверочный код + + + 获取验证码 + Получить проверочный код + + + + UpdateWorker + + Update + Обновление + + + Please plug in and then install updates. + Пожалуйста, подключитесь, а затем установите обновления. + + + + UsersWithTheSameName + + Return + Возврат + + + Please select the account for login + Пожалуйста, выберите учетную запись для входа + + + Local Account + Локальная учетная запись + + + Domain Account + Аккаунт домена WarningContent - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. Программы препятствуют выключению компьютера, принудительное выключение может привести к потере данных. - - - - - To close the program, click Cancel, and then close the program. Чтобы закрыть программу, нажмите кнопку Отмена, а затем закройте ее. - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. Программы препятствуют перезагрузке компьютера, принудительная перезагрузка может привести к потере данных. - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. Программы препятствуют приостановке работы компьютера, принудительная приостановка может привести к потере данных. - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. Программы препятствуют переходу компьютера в спящий режим, принудительный переход в спящий режим может привести к потере данных. - The programs are preventing the computer from log out, and forcing log out may cause data loss. Программы препятствуют выходу компьютера из системы, принудительный выход из системы может привести к потере данных. - - - Shut down Выключить - - - Reboot Перезагрузить - Suspend Приостановить - Hibernate Спящий режим - - Log out Выйти из системы - Are you sure you want to shut down? Вы уверены, что хотите выключить? - Are you sure you want to reboot? Вы действительно хотите перезагрузить? - Are you sure you want to log out? Вы действительно хотите выйти из системы? + + Update and Shut Down + Обновить и выключить + + + Update and Reboot + Обновить и перезагрузить + + + Closing the programs and shutting down, please wait... + Закрытие программ и завершение работы, пожалуйста, подождите... + + + Closing the programs and rebooting, please wait... + Закрытие программ и перезагрузка, пожалуйста подождите... + + + Closing the programs and logging out, please wait... + Закрытие программ и выход из системы, пожалуйста подождите... + + + + dss::module::AssistLoginWidget + + Automatic login + Автоматическая авторизация + + + + dss::module::NetworkModule + + Turn on + Включить + + + Turn off + Выключить + \ No newline at end of file diff --git a/translations/dde-session-shell_ru_UA.ts b/translations/dde-session-shell_ru_UA.ts new file mode 100644 index 00000000..1ca098c3 --- /dev/null +++ b/translations/dde-session-shell_ru_UA.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_sc.ts b/translations/dde-session-shell_sc.ts new file mode 100644 index 00000000..4ffb1040 --- /dev/null +++ b/translations/dde-session-shell_sc.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_si.ts b/translations/dde-session-shell_si.ts index 22f7adc3..a00f8877 100644 --- a/translations/dde-session-shell_si.ts +++ b/translations/dde-session-shell_si.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය වසා දැමීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය වසා දැමීම, දත්ත අස්ථානගත වීමට හේතු විය හැක. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - වැඩසටහන වසා දැමීමට, අවලංගු කර, පසුව වැඩසටහන වසා දමන්න. + Verification successful + සත්‍යාපනය සාර්ථකයි + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය නැවත පණගැන්වීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය පණ ගැන්වීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය අත්හිටුවීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය අත්හිටුවීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය ශිශිරතරණය කිරීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය ශිශිරතරණය කිරීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය පරිශීලක ගිණුමෙන් ඉවත් වීම වළක්වයි. බලහත්කාරයෙන් පරිශීලක ගිණුමෙන් ඉවත් වීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - වසා දමන්න + Verify your fingerprint + - - - - - Reboot - පද්ධතිය නැවත අරඹන්න + Verification successful + සත්‍යාපනය සාර්ථකයි + + + Verification failed, %n chances left + - - - Suspend - තාවකාලිකව වසාදමන්න + Verification failed, only one chance left + - - - Hibernate - ශිශිරකරණය කරන්න + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - ඉවත් වන්න + Iris ID + - - Are you sure you want to shut down? - පද්ධතිය වසා දැමීමට අවශ්‍ය බව ඔබට විශ්වාසද? + Verification successful + සත්‍යාපනය සාර්ථකයි + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - පද්ධතිය නැවත ආරම්භ කිරීමට අවශ්‍ය බව ඔබට විශ්වාසද? + Verification failed, only one chance left + - - Are you sure you want to log out? - පරිශීලක ගිණුමෙන් ඉවත් වීමට අවශ්‍ය බව ඔබට විශ්වාසද? + Verify your Iris ID + - - Lock - අගුළු දමන්න + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - පරීශීලක වෙනස් කිරීම + Please plug in the security key + - - Switch system - පද්ධතිය වෙනස් කිරීම + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + සත්‍යාපනය සාර්ථකයි + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password වැරදි මුරපදයකි - - The account or password is not correct. Please enter again. - ගිණුම හෝ මුරපදය නිවැරදි නොවේ. කරුණාකර නැවත උත්සාහ කරන්න. + Password + මුර පදය + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + සත්‍යාපනය සාර්ථකයි + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + පරිශීලක ගිණුම + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + මුරපදය කල් ඉකුත් වී ඇත, කරුණාකර වෙනස් කරන්න + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + වැරදි මුරපදයකි InhibitWarnView - Cancel අවලංගු කරන්න + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen තිරය අගුළුලන්න - Failed to lock screen තිරය අගුළු ලෑම අසාර්ථකයි @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually ඇඟිලි සලකුණු සත්‍යාපනය කල් ඉකුත් වී ඇත, කරුණාකර ඔබගේ මුරපදය ඇතුලත් කරන්න - Failed to match fingerprint ඇඟිලි සලකුණු ගැලපීම අසාර්ථකයි - - - Wrong Password - වැරදි මුරපදයකි - MultiUsersWarningView - Cancel අවලංගු කරන්න - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? ඉහත පරිශීලකයින් තවමත් පුරනය වී සිටින අතර පද්ධතිය වසා දැමීම හේතුවෙන් දත්ත අස්ථානගතවිය හැකිය, මෙය සිදුකිරීම අවශ්‍ය යැයි ඔබට විශ්වාසද? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? ඉහත පරිශීලකයින් තවමත් පුරනය වී සිටින අතර පද්ධතිය නැවත ආරම්භ කිරීම හේතුවෙන් දත්ත අස්ථානගතවිය හැකිය, මෙය සිදුකිරීම අවශ්‍ය යැයි ඔබට විශ්වාසද? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down වසා දමන්න - - Reboot පද්ධතිය නැවත අරඹන්න - - Suspend තාවකාලිකව වසාදමන්න - - Hibernate ශිශිරකරණය කරන්න + + Lock + අගුළු දමන්න + + + Log out + ඉවත් වන්න + + + Switch user + පරීශීලක වෙනස් කිරීම + + + Switch system + පද්ධතිය වෙනස් කිරීම + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor පද්ධති පිරික්සුම අරඹන්න - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - මුරපදය කල් ඉකුත් වී ඇත, කරුණාකර වෙනස් කරන්න + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + - - New password - නව මුරපදය + 获取验证码 + + + + UpdateWorker - - Repeat password - මුරපදය නැවත ඇතුලත් කරන්න + Update + - - Failed to change your password - ඔබගේ මුරපදය වෙනස් කිරීම අසාර්ථකයි + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - මුරපදය ඉතා දුර්වලයි + Return + - - Please enter the new password - කරුණාකර නව මුරපදය ඇතුළත් කරන්න + Please select the account for login + - - Please repeat the new password - කරුණාකර නව මුරපදය නැවත ඇතුලත් කරන්න + Local Account + - - Passwords do not match - මුරපද නොගැලපේ + Domain Account + - UserLoginWidget + WarningContent - - Password - මුර පදය + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය වසා දැමීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය වසා දැමීම, දත්ත අස්ථානගත වීමට හේතු විය හැක. - - Account - පරිශීලක ගිණුම + To close the program, click Cancel, and then close the program. + වැඩසටහන වසා දැමීමට, අවලංගු කර, පසුව වැඩසටහන වසා දමන්න. - - Please enter the account - පරිශිලක ගිණුම ඇතුලත් කරන්න + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය නැවත පණගැන්වීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය පණ ගැන්වීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. - - Please enter the password - කරුණාකර මුරපදය ඇතුළත් කරන්න + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය අත්හිටුවීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය අත්හිටුවීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය ශිශිරතරණය කිරීම වළක්වයි. බලහත්කාරයෙන් පද්ධතිය ශිශිරතරණය කිරීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + දැනට ක්‍රියාත්මක වැඩසටහන් මඟින් පරිගණකය පරිශීලක ගිණුමෙන් ඉවත් වීම වළක්වයි. බලහත්කාරයෙන් පරිශීලක ගිණුමෙන් ඉවත් වීම දත්ත අස්ථානගත වීමට හේතු විය හැකිය. + + + Shut down + වසා දමන්න + + + Reboot + පද්ධතිය නැවත අරඹන්න + + + Suspend + තාවකාලිකව වසාදමන්න + + + Hibernate + ශිශිරකරණය කරන්න + + + Log out + ඉවත් වන්න + + + Are you sure you want to shut down? + පද්ධතිය වසා දැමීමට අවශ්‍ය බව ඔබට විශ්වාසද? + + + Are you sure you want to reboot? + පද්ධතිය නැවත ආරම්භ කිරීමට අවශ්‍ය බව ඔබට විශ්වාසද? + + + Are you sure you want to log out? + පරිශීලක ගිණුමෙන් ඉවත් වීමට අවශ්‍ය බව ඔබට විශ්වාසද? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + ක්‍රියාත්මක කරන්න + + + Turn off + වසා දමන්න \ No newline at end of file diff --git a/translations/dde-session-shell_sk.ts b/translations/dde-session-shell_sk.ts index b3df68f1..464c9f6d 100644 --- a/translations/dde-session-shell_sk.ts +++ b/translations/dde-session-shell_sk.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Programy bránia vypnutiu počítača a nútené vypnutie môže spôsobiť stratu údajov. + Face ID + Face ID - - - - - - To close the program, click Cancel, and then close the program. - Ak chcete program ukončiť, kliknite na tlačidlo Zrušiť a potom program zatvorte. + Verification successful + Overenie bolo úspešné + + + Verification failed, %n chances left + Overenie zlyhalo, ostáva %d pokusOverenie zlyhalo, ostávajú %d pokusyOverenie zlyhalo, ostáva %d pokusov Overenie zlyhalo, ostáva %d pokusov - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Programy bránia počítaču v reštartovaní a nútené reštartovanie môže spôsobiť stratu údajov. + Verification failed, only one chance left + Overenie zlyhalo, ostáva iba jeden pokus - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Programy bránia pozastaveniu počítača a nútené pozastavenie môže spôsobiť stratu údajov. + Verify your Face ID + Overte svoje Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Programy bránia prechodu počítača do režimu dlhodobého spánku a nútený režim dlhodobého spánku môže spôsobiť stratu údajov. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Programy bránia počítaču v odhlásení a nútené odhlásenie môže spôsobiť stratu údajov. + Device unavailable! + Zariadenie nie je dostupné! + + + AuthFingerprint - - - - - Shut down - Vypnúť + Verify your fingerprint + Overte svoj odtlačok prsta - - - - - Reboot - Reštart + Verification successful + Overenie bolo úspešné + + + Verification failed, %n chances left + Overenie zlyhalo, ostáva %d pokusOverenie zlyhalo, ostávajú %d pokusyOverenie zlyhalo, ostáva %d pokusov Overenie zlyhalo, ostáva %d pokusov - - - Suspend - Uspať + Verification failed, only one chance left + Overenie zlyhalo, ostáva iba jeden pokus - - - Hibernate - Hibernácia + Fingerprint locked, use password please + + + + AuthIris - - - - Log out - Odhlásiť + Iris ID + Iris ID - - Are you sure you want to shut down? - Určite chcete vypnúť? + Verification successful + Overenie bolo úspešné + + + Verification failed, %n chances left + Overenie zlyhalo, ostáva %d pokusOverenie zlyhalo, ostávajú %d pokusyOverenie zlyhalo, ostáva %d pokusov Overenie zlyhalo, ostáva %d pokusov - - Are you sure you want to reboot? - Naozaj chcete reštartovať? + Verification failed, only one chance left + Overenie zlyhalo, ostáva iba jeden pokus - - Are you sure you want to log out? - Určite sa chcete odhlásiť? + Verify your Iris ID + Overte svoje Iris ID - - Lock - Zamknúť + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Prepnúť užívateľa + Please plug in the security key + - - Switch system - Prepnúť systém + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + Overenie bolo úspešné + + + Verification failed, %n chances left + Overenie zlyhalo, ostáva %d pokusOverenie zlyhalo, ostávaju %d pokusyOverenie zlyhalo, ostáva %d pokusov Overenie zlyhalo, ostáva %d pokusov + + + Verification failed, only one chance left + Overenie zlyhalo, ostáva iba jeden pokus + - Wrong Password Chybné heslo - - The account or password is not correct. Please enter again. - Účet alebo heslo nie je správne. Zadajte ho prosím znova. + Password + Heslo + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + Obnoviť heslo + + + Forgot password? + Zabudli ste heslo? + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + Obnoviť heslo + + + Forgot password? + Zabudli ste heslo? + + + + AuthUKey + + Verification successful + Overenie bolo úspešné + + + Verification failed, %n chances left + Overenie zlyhalo, ostáva %d pokusOverenie zlyhalo, ostávajú %d pokusyOverenie zlyhalo, ostáva %d pokusov Overenie zlyhalo, ostáva %d pokusov + + + Verification failed, only one chance left + Overenie zlyhalo, ostáva iba jeden pokus + + + Wrong PIN + Nesprávny PIN + + + UKey is required + + + + Enter your PIN + Zadajte svoj PIN + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Účet + + + Your password will expire in %n days, please change it timely + Platnosť vašeho hesla vyprší za %d deň, zmeňte si ho prosím včasPlatnosť vašeho hesla vyprší za %d dni, zmeňte si ho prosím včasPlatnosť vašeho hesla vyprší za %d dní, zmeňte si ho prosím včasPlatnosť vašeho hesla vyprší za %d dní, zmeňte si ho prosím včas + + + Password expired, please change + Platnosť hesla vypršala, zmeňte ho prosím + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + Nesprávny účet + + + Wrong Password + Chybné heslo InhibitWarnView - Cancel Zrušiť + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Zamknúť obrazovku - Failed to lock screen Zlyhalo zamknutie obrazovky @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Časový limit overenia odtlačku prsta vypršal. Prosím zadajte heslo ručne - Failed to match fingerprint Zlyhalo porovnanie odtlačkov prstov - - - Wrong Password - Chybné heslo - MultiUsersWarningView - Cancel Zrušiť - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Vyššie uvedení užívatelia sú stále prihlásení a údaje sa stratia v dôsledku vypnutia, ste si istí, že ich chcete vypnúť? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Vyššie uvedení užívatelia sú stále prihlásení a údaje sa stratia v dôsledku reštartu, ste si istí, že chcete reštartovať? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Vypnúť - - Reboot Reštart - - Suspend Uspať - - Hibernate Hibernácia + + Lock + Zamknúť + + + Log out + Odhlásiť + + + Switch user + Prepnúť užívateľa + + + Switch system + Prepnúť systém + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Spustenie systémového monitora - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Platnosť hesla vypršala, zmeňte ho prosím + 发送验证码 + + + + 请输入手机号 + - - New password - Nové heslo + 请输入验证码 + - - Repeat password - Zopakujte heslo + 获取验证码 + + + + UpdateWorker - - Failed to change your password - Zlyhala zmena vášho hesla + Update + - - Password too weak - Heslo je príliš slabé + Please plug in and then install updates. + + + + UsersWithTheSameName - - Please enter the new password - Prosím, zadajte nové heslo + Return + - - Please repeat the new password - Prosím, zopakujte nové heslo + Please select the account for login + - - Passwords do not match - Heslá sa nezhodujú + Local Account + + + + Domain Account + - UserLoginWidget + WarningContent - - Password - Heslo + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Programy bránia vypnutiu počítača a nútené vypnutie môže spôsobiť stratu údajov. - - Account - Účet + To close the program, click Cancel, and then close the program. + Ak chcete program ukončiť, kliknite na tlačidlo Zrušiť a potom program zatvorte. - - Please enter the account - Vložte prosím názov účtu + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Programy bránia počítaču v reštartovaní a nútené reštartovanie môže spôsobiť stratu údajov. - - Please enter the password - Vložte prosím heslo + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Programy bránia pozastaveniu počítača a nútené pozastavenie môže spôsobiť stratu údajov. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Programy bránia prechodu počítača do režimu dlhodobého spánku a nútený režim dlhodobého spánku môže spôsobiť stratu údajov. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Programy bránia počítaču v odhlásení a nútené odhlásenie môže spôsobiť stratu údajov. + + + Shut down + Vypnúť + + + Reboot + Reštart + + + Suspend + Uspať + + + Hibernate + Hibernácia + + + Log out + Odhlásiť + + + Are you sure you want to shut down? + Určite chcete vypnúť? + + + Are you sure you want to reboot? + Naozaj chcete reštartovať? + + + Are you sure you want to log out? + Určite sa chcete odhlásiť? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Zapnúť + + + Turn off + Vypnúť \ No newline at end of file diff --git a/translations/dde-session-shell_sl.ts b/translations/dde-session-shell_sl.ts index c397a857..bba26787 100644 --- a/translations/dde-session-shell_sl.ts +++ b/translations/dde-session-shell_sl.ts @@ -1,9 +1,9 @@ - + - AuthFingerprint + AuthFace - Verify your fingerprint - Preverite prstni odtis + Face ID + Verification successful @@ -11,99 +11,103 @@ Verification failed, %n chances left - Preverjanje ni uspelo. Še %n poskusPreverjanje ni uspelo. Še %n poskusaPreverjanje ni uspelo. Še %n poskusiPreverjanje ni uspelo. Še %n poskusov + Verification failed, only one chance left Neuspešna overitev. Ostal je le še en poskus - Fingerprint locked, use password please - Prstni odtis je zaklenjen, uporabite geslo + Verify your Face ID + - - Please try again %n minute(s) later - Pokusite znova %n minuto kasnejePokusite znova %n minuti kasnejePokusite znova %n minute kasnejePokusite znova %n minut kasneje + + Face ID locked, use password please + + + + Device unavailable! + - AuthPassword + AuthFingerprint + + Verify your fingerprint + Preverite prstni odtis + Verification successful Uspešno preverjanje Verification failed, %n chances left - Preverjanje ni uspelo. Še %n poskusPreverjanje ni uspelo. Še %n poskusaPreverjanje ni uspelo. Še %n poskusiPreverjanje ni uspelo. Še %n poskusov + Verification failed, only one chance left Neuspešna overitev. Ostal je le še en poskus - Wrong Password - Napačno geslo - - - Password - Geslo - - - Please try again %n minute(s) later - Pokusite znova %n minuto kasnejePokusite znova %n minuti kasnejePokusite znova %n minute kasnejePokusite znova %n minut kasneje + Fingerprint locked, use password please + Prstni odtis je zaklenjen, uporabite geslo - AuthSingle + AuthIris - Please try again 1 minute later - Pokusite znova minuto kasneje - - - Please try again %n minutes later - Pokusite znova %n minuto kasnejePokusite znova %n minuti kasnejePokusite znova %n minute kasnejePokusite znova %n minut kasneje + Iris ID + - - - AuthUKey Verification successful Uspešno preverjanje Verification failed, %n chances left - Preverjanje ni uspelo. Še %n poskusPreverjanje ni uspelo. Še %n poskusaPreverjanje ni uspelo. Še %n poskusiPreverjanje ni uspelo. Še %n poskusov + Verification failed, only one chance left Neuspešna overitev. Ostal je le še en poskus - Wrong PIN - Napačen PIN + Verify your Iris ID + - UKey is required - Zahtevan je UKey + Iris ID locked, use password please + + + + AuthPasskey - Enter your PIN - Vnesite PIN + Please plug in the security key + - - Please try again %n minute(s) later - Pokusite znova %n minuto kasnejePokusite znova %n minuti kasnejePokusite znova %n minute kasnejePokusite znova %n minut kasneje + + Verification successful + + + + Verification failed + + + + Identifying the security key + - AuthenticationModule + AuthPassword Verification successful Uspešno preverjanje Verification failed, %n chances left - Preverjanje ni uspelo. Še %n poskusPreverjanje ni uspelo. Še %n poskusaPreverjanje ni uspelo. Še %n poskusiPreverjanje ni uspelo. Še %n poskusov + Verification failed, only one chance left @@ -114,111 +118,116 @@ Napačno geslo - Wrong PIN - Napačen PIN - - - UKey is required - Zahtevan je UKey + Password + Geslo - Verify your fingerprint - Preverite prstni odtis + Please try again 1 minute later + Pokusite znova minuto kasneje - - Password - Geslo + + Please try again %n minutes later + - Enter your PIN - Vnesite PIN + Reset Password + Ponastavi geslo - Fingerprint locked, use password please - Prstni odtis je zaklenjen, uporabite geslo + Forgot password? + + + + AuthSingle Please try again 1 minute later Pokusite znova minuto kasneje Please try again %n minutes later - Pokusite znova %n minuto kasnejePokusite znova %n minuti kasnejePokusite znova %n minute kasnejePokusite znova %n minut kasneje + - - - ContentWidget - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Programi preprečujejo računalniku, da bi se zaustavil, prisilna zaustavitev pa lahko povzroči izgubo podatkov. + Reset Password + Ponastavi geslo - To close the program, click Cancel, and then close the program. - Da bi program zaprli, klknite Prekini in nato zaprite program. + Forgot password? + + + + AuthUKey - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Programi preprečujejo računalniku, da bi se ponovno zagnal, prisilna zaustavitev pa lahko povzroči izgubo podatkov. + Verification successful + Uspešno preverjanje - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Programi preprečujejo računalniku, da bi obmiroval, prisilna zaustavitev pa lahko povzroči izgubo podatkov. + + Verification failed, %n chances left + - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Programi preprečujejo računalniku, da bi zaspal, prisilna zaustavitev pa lahko povzroči izgubo podatkov. + Verification failed, only one chance left + Neuspešna overitev. Ostal je le še en poskus - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Programi preprečujejo računalniku, da bi se odjavil prisilna zaustavitev pa lahko povzroči izgubo podatkov. + Wrong PIN + Napačen PIN - Shut down - Zaustavitev sistema + UKey is required + Zahtevan je UKey - Reboot - Ponovni zagon + Enter your PIN + Vnesite PIN - - Suspend - Mirovanje + + Please try again %n minute(s) later + - Hibernate - Spanje + Please try again 1 minute later + Pokusite znova minuto kasneje - - Log out - Odjava + + Please try again %n minutes later + + + + AuthWidget - Are you sure you want to shut down? - Ste prepričani, da želite zaustaviti sistem? + Account + Račun - - Are you sure you want to reboot? - Ste prepričani, da žeelite ponovni zagon? + + Your password will expire in %n days, please change it timely + - Are you sure you want to log out? - Ste preričani, da se želite odjaviti? + Password expired, please change + Geslo je poteklo. Zamenjajte ga - Lock - Zakleni + Your password has expired. Please contact the administrator to change it + - Switch user - Zamenjaj uporabnika + Terminal locked, please contact administrator + + + + DeepinAuthFramework - Switch system - Zamenjaj sistem + Wrong Password + - GreeterWorkek + GreeterWorker Wrong account Napačen račun @@ -234,6 +243,17 @@ Cancel Prekliči + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent @@ -250,11 +270,11 @@ LockWorker Fingerprint verification timed out, please enter your password manually - Preverjanje prstnega odtisa ni bilo uspešno, vnesite geslo + Zaznavanje prstnega odtisa ni uspelo, vnesite geslo Failed to match fingerprint - Neustrezen prstni odtis + Prstni odtis se ne ujema @@ -272,6 +292,13 @@ Navedeni uporabniki so še vedno prijavljeni in njihovi podatki bodo izgubljeni, če bo sistem ponovno zagnan. Želite vseeno zaustaviti sistem? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget @@ -306,6 +333,14 @@ Switch system Zamenjaj sistem + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor @@ -315,22 +350,52 @@ - UserLoginWidget + UdcpMFALoginWidget - Account - Račun + 发送验证码 + - Verify your fingerprint - Preverite prstni odtis + 请输入手机号 + - - Your password will expire in %n days, please change it timely - Vaše geslo bo poteklo v %n dnevu. Pravočasno ga zamenjajteVaše geslo bo poteklo v %n dneh. Pravočasno ga zamenjajteVaše geslo bo poteklo v %n dneh. Pravočasno ga zamenjajteVaše geslo bo poteklo v %n dneh. Pravočasno ga zamenjajte + + 请输入验证码 + - Password expired, please change - Geslo je poteklo. Zamenjajte ga + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + @@ -391,5 +456,43 @@ Are you sure you want to log out? Ste preričani, da se želite odjaviti? + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Vklopi + + + Turn off + Izklopi + \ No newline at end of file diff --git a/translations/dde-session-shell_sq.ts b/translations/dde-session-shell_sq.ts index 0d7bb277..cea6a8a7 100644 --- a/translations/dde-session-shell_sq.ts +++ b/translations/dde-session-shell_sq.ts @@ -27,7 +27,7 @@ Device unavailable! - + Pajisje e pakapshme! @@ -80,6 +80,25 @@ Iris ID e kyçur, ju lutemi, përdorni fjalëkalimin + + AuthPasskey + + Please plug in the security key + Ju lutemi, futni kyçin e sigurisë + + + Verification successful + Verifikim i suksesshëm + + + Verification failed + Verifikimi dështoi + + + Identifying the security key + Po identifikohet kyçi i sigurisë + + AuthPassword @@ -189,7 +208,22 @@ Password expired, please change - Fjalëkalimi ndryshoi, ju lutemi, ndryshojeni + Fjalëkalimi skadoi, ju lutemi, ndryshojeni + + + Your password has expired. Please contact the administrator to change it + Fjalëkalimi juaj ka skaduar. Ju lutemi, lidhuni me përgjegjësin që ta ndryshojë + + + Terminal locked, please contact administrator + Terminal i kyçur, ju lutemi, lidhuni me përgjegjësin + + + + DeepinAuthFramework + + Wrong Password + Fjalëkalim i Gabuar @@ -209,6 +243,17 @@ Cancel Anuloje + + The reason of inhibit. + Arsyeja e pengimit. + + + + LighterGreeter + + Standard Mode + Mënyra Standarde + LockContent @@ -288,6 +333,14 @@ Switch system Ndërroni sistem + + Update and Shut Down + Përditësoje dhe Fiku + + + Update and Reboot + Përditësoje dhe Rinisu + SystemMonitor @@ -296,31 +349,80 @@ Nis mbikëqyrës sistemi + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + Përditësim + + + Please plug in and then install updates. + Ju lutemi, vëreni në prizë dhe mandej instaloni përditësimet. + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + Ju lutemi, përzgjidhni llogarinë për hyrje + + + Local Account + Llogari Vendore + + + Domain Account + Llogari Përkatësie + + WarningContent The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Ka programe që e pengojnë fikjen e kompjuterit, dhe fikja me zor mund të sjellë humbje të dhënash. + Ka programe që e pengojnë fikjen e kompjuterit dhe fikja me zor mund të sjellë humbje të dhënash. To close the program, click Cancel, and then close the program. - Që të mbyllet programi, klikoni mbi “Anuloje”, dhe mandej mbyllni programin. + Që të mbyllet programi, klikoni mbi “Anuloje” dhe mandej mbyllni programin. The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Ka programe që e pengojnë rinisjen e kompjuterit, dhe rinisja me zor mund të sjellë humbje të dhënash. + Ka programe që e pengojnë rinisjen e kompjuterit dhe rinisja me zor mund të sjellë humbje të dhënash. The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Ka programe që e pengojnë pezullimin e kompjuterit, dhe pezullimi me zor mund të sjellë humbje të dhënash. + Ka programe që e pengojnë pezullimin e kompjuterit dhe pezullimi me zor mund të sjellë humbje të dhënash. The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Ka programe që e pengojnë plogështimin e kompjuterit, dhe plogështimi me zor mund të sjellë humbje të dhënash. + Ka programe që e pengojnë plogështimin e kompjuterit dhe plogështimi me zor mund të sjellë humbje të dhënash. The programs are preventing the computer from log out, and forcing log out may cause data loss. - Ka programe që e pengojnë kompjuterin të bëjë dalje nga llogaria, dhe dalja me zor mund të sjellë humbje të dhënash. + Ka programe që e pengojnë kompjuterin të bëjë dalje nga llogaria dhe dalja me zor mund të sjellë humbje të dhënash. Shut down @@ -354,6 +456,33 @@ Are you sure you want to log out? Jeni i sigurt se doni të dilet? + + Update and Shut Down + Përditësoje dhe Fiku + + + Update and Reboot + Përditësoje dhe Rinisu + + + Closing the programs and shutting down, please wait... + Po mbyllen programet dhe po bëhet fikja, ju lutemi, prisni… + + + Closing the programs and rebooting, please wait... + Po mbyllen programet dhe po bëhet rinisje, ju lutemi, prisni… + + + Closing the programs and logging out, please wait... + Po mbyllen programet dhe po bëhet dalje nga llogaria, ju lutemi, prisni… + + + + dss::module::AssistLoginWidget + + Automatic login + Hyrje e automatizuar + dss::module::NetworkModule diff --git a/translations/dde-session-shell_sr.ts b/translations/dde-session-shell_sr.ts index 37fdc05e..bcf50123 100644 --- a/translations/dde-session-shell_sr.ts +++ b/translations/dde-session-shell_sr.ts @@ -1,9 +1,9 @@ - + - AuthFingerprint + AuthFace - Verify your fingerprint - Верификујте отисак прста + Face ID + Verification successful @@ -11,99 +11,103 @@ Verification failed, %n chances left - Неуспешна верификација, имате још %n покушајНеуспешна верификација, имате још %n покушајаНеуспешна верификација, имате још %n покушаја + Verification failed, only one chance left Неуспешна верификација, имате још један покушај - Fingerprint locked, use password please - Отисак прста је закључан, употребите лозинку + Verify your Face ID + - - Please try again %n minute(s) later - Покушајте поново за %n минутПокушајте поново за %n минутаПокушајте поново за %n минута + + Face ID locked, use password please + + + + Device unavailable! + - AuthPassword + AuthFingerprint + + Verify your fingerprint + Верификујте отисак прста + Verification successful Успешна верификација Verification failed, %n chances left - Неуспешна верификација, имате још %n покушајНеуспешна верификација, имате још %n покушајаНеуспешна верификација, имате још %n покушаја + Verification failed, only one chance left Неуспешна верификација, имате још један покушај - Wrong Password - Погрешна лозинка - - - Password - Лозинка - - - Please try again %n minute(s) later - Покушајте поново за %n минутПокушајте поново за %n минутаПокушајте поново за %n минута + Fingerprint locked, use password please + Отисак прста је закључан, употребите лозинку - AuthSingle + AuthIris - Please try again 1 minute later - Покушајте поново за 1 минут + Iris ID + - - Please try again %n minutes later - Покушајте поново за %n минутПокушајте поново за %n минутаПокушајте поново за %n минута - - - - AuthUKey Verification successful Успешна верификација Verification failed, %n chances left - Неуспешна верификација, имате још %n покушајНеуспешна верификација, имате још %n покушајаНеуспешна верификација, имате још %n покушаја + Verification failed, only one chance left Неуспешна верификација, имате још један покушај - Wrong PIN - Погрешан ПИН + Verify your Iris ID + - UKey is required - Потребан је У-Кључ + Iris ID locked, use password please + + + + AuthPasskey - Enter your PIN - Унесите ПИН + Please plug in the security key + - - Please try again %n minute(s) later - Покушајте поново за %n минутПокушајте поново за %n минутаПокушајте поново за %n минута + + Verification successful + + + + Verification failed + + + + Identifying the security key + - AuthenticationModule + AuthPassword Verification successful Успешна верификација Verification failed, %n chances left - Неуспешна верификација, имате још %n покушајНеуспешна верификација, имате још %n покушајаНеуспешна верификација, имате још %n покушаја + Verification failed, only one chance left @@ -114,111 +118,116 @@ Погрешна лозинка - Wrong PIN - Погрешан ПИН - - - UKey is required - Потребан је У-Кључ + Password + Лозинка - Verify your fingerprint - Верификујте отисак прста + Please try again 1 minute later + Покушајте поново за 1 минут - - Password - Лозинка + + Please try again %n minutes later + - Enter your PIN - Унесите ПИН + Reset Password + - Fingerprint locked, use password please - Отисак прста је закључан, употребите лозинку + Forgot password? + + + + AuthSingle Please try again 1 minute later Покушајте поново за 1 минут Please try again %n minutes later - Покушајте поново за %n минутПокушајте поново за %n минутаПокушајте поново за %n минута + - - - ContentWidget - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Програми спречавају искључивање. Принудно искључивање може изазвати губитак података. + Reset Password + - To close the program, click Cancel, and then close the program. - Да затворите програм, кликните на Откажи, затим затворите. + Forgot password? + + + + AuthUKey - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Програми спречавају поновно покретање. Принудно поновно покретање може изазвати губитак података. + Verification successful + Успешна верификација - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Програми спречавају обуставу. Принудно обустављање може изазвати губитак података. + + Verification failed, %n chances left + - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Програми спречавају хибернацију. Принудна хибернација може изазвати губитак података. + Verification failed, only one chance left + Неуспешна верификација, имате још један покушај - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Програми спречавају одјављивање. Принудно одјављивање може изазвати губитак података. + Wrong PIN + Погрешан ПИН - Shut down - Искључи + UKey is required + Потребан је У-Кључ - Reboot - Поново покрени + Enter your PIN + Унесите ПИН - - Suspend - Обустави + + Please try again %n minute(s) later + - Hibernate - Хибернација + Please try again 1 minute later + Покушајте поново за 1 минут - - Log out - Одјави се + + Please try again %n minutes later + + + + AuthWidget - Are you sure you want to shut down? - Заиста желите да искључите? + Account + Налог - - Are you sure you want to reboot? - Заиста желите да поново покренете? + + Your password will expire in %n days, please change it timely + - Are you sure you want to log out? - Заиста желите да се одјавите? + Password expired, please change + Лозинка је истекла, промените је - Lock - Закључај + Your password has expired. Please contact the administrator to change it + - Switch user - Промени корисника + Terminal locked, please contact administrator + + + + DeepinAuthFramework - Switch system - Промени систем + Wrong Password + - GreeterWorkek + GreeterWorker Wrong account Погрешан налог @@ -234,6 +243,17 @@ Cancel Откажи + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent @@ -272,6 +292,13 @@ Горе наведени корисници су и даље пријављени и њихови несачувани подаци ће нестати. Заиста желите да поново покренете? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget @@ -306,6 +333,14 @@ Switch system Промени систем + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor @@ -315,22 +350,52 @@ - UserLoginWidget + UdcpMFALoginWidget - Account - Налог + 发送验证码 + - Verify your fingerprint - Верификујте отисак прста + 请输入手机号 + - - Your password will expire in %n days, please change it timely - Лозинка истиче за %n дан, промените је на времеЛозинка истиче за %n дана, промените је на времеЛозинка истиче за %n дан(а), промените је на време + + 请输入验证码 + - Password expired, please change - Лозинка је истекла, промените је + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + @@ -391,5 +456,43 @@ Are you sure you want to log out? Заиста желите да се одјавите? + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Укључи + + + Turn off + Искључи + \ No newline at end of file diff --git a/translations/dde-session-shell_sv.ts b/translations/dde-session-shell_sv.ts index 493f46f6..1a86fbae 100644 --- a/translations/dde-session-shell_sv.ts +++ b/translations/dde-session-shell_sv.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Stäng av + Verify your fingerprint + - - - - - Reboot - Starta om + Verification successful + - - - - Suspend - Vänteläge + + Verification failed, %n chances left + - - - Hibernate - Viloläge + Verification failed, only one chance left + - - - - Log out - Logga ut + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - Är du säker du vill stänga av? + Iris ID + - - Are you sure you want to reboot? - Är du säker du vill starta om? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - Är du säker du vill logga ut? + Verification failed, only one chance left + - - Lock - Lås + Verify your Iris ID + - - Switch user - Byt användare + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password - Verifiera ditt fingeravtryck eller lösenord + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Felaktigt Lösenord - - The domain account or password is not correct. Please enter again. - Domänkontot eller lösenordet är ej korrekt. Var god försök igen + Password + Lösenord + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Felaktigt Lösenord InhibitWarnView - Cancel Avbryt + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - Domänkonto - - - Fingerprint verification timed out, please enter your password manually Fingeravtryck tog för lång tid, vänligen skriv in lösenordet istället - Failed to match fingerprint Misslyckades med att matcha fingeravtryck - - - Wrong Password - Felaktigt Lösenord - MultiUsersWarningView - Cancel Avbryt - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Ovanstående användare är fortfarande inloggade och data kommer att gå förlorade på grund av avstängning, är du säker du vill fortsätta? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Ovanstående användare är fortfarande inloggade och data kommer gå förlorade på grund av omstart, är du säker du vill fortsätta? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Stäng av - - Reboot Starta om - - Suspend Vänteläge - - Hibernate Viloläge + + Lock + Lås + + + Log out + Logga ut + + + Switch user + Byt användare + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Starta systemövervakare - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password - Repetera lösenord + Update + - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password - Ange det nya lösenordet + Please select the account for login + - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Lösenord + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Ange ditt lösenord för att starta om + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down - Ange ditt lösenord för att stänga av + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Stäng av + + + Reboot + Starta om + + + Suspend + Vänteläge + + + Hibernate + Viloläge + + + Log out + Logga ut + + + Are you sure you want to shut down? + Är du säker du vill stänga av? + + + Are you sure you want to reboot? + Är du säker du vill starta om? + + + Are you sure you want to log out? + Är du säker du vill logga ut? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_sv_SE.ts b/translations/dde-session-shell_sv_SE.ts new file mode 100644 index 00000000..6785130d --- /dev/null +++ b/translations/dde-session-shell_sv_SE.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_sw.ts b/translations/dde-session-shell_sw.ts index 4e2bdd6c..40a4f365 100644 --- a/translations/dde-session-shell_sw.ts +++ b/translations/dde-session-shell_sw.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - Zima + Verify your fingerprint + - - - - - Reboot - Washa upya + Verification successful + - - - - Suspend - Ahirisha + + Verification failed, %n chances left + - - - Hibernate - Sinzia fofofo + Verification failed, only one chance left + - - - - Log out - Aga + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? - Ni kweli unataka kuzima? + Iris ID + - - Are you sure you want to reboot? - Ni kweli unataka kuwasha upya? + Verification successful + + + + Verification failed, %n chances left + - - Are you sure you want to log out? - Ni kweli unataka kuaga? + Verification failed, only one chance left + - - Lock - Funga skrini + Verify your Iris ID + - - Switch user - Badili mtumiaji + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + + + Verification successful + + - - Verify your fingerprint or password - Hakikisha nywila yako ama alama cha kidole + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Nywila si Sahihi - - The domain account or password is not correct. Please enter again. - Mtumiaji ama nywila ni mbaya. Tafadhali jaribu tena. + Password + Nywila + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Nywila si Sahihi InhibitWarnView - Cancel Katisha + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually Kuthbitisha alama ya kidole imengoja zaidi, tafadhali tumia nywila - Failed to match fingerprint Alama ya kidole hailingana - - - Wrong Password - Nywila si Sahihi - MultiUsersWarningView - Cancel Katisha - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Zima - - Reboot Washa upya - - Suspend Ahirisha - - Hibernate Sinzia fofofo + + Lock + Funga skrini + + + Log out + Aga + + + Switch user + Badili mtumiaji + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Anza kichunguzi ya mfumo - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 - - New password + 获取验证码 + + + UpdateWorker - - Repeat password - Nwyila tena + Update + - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password - Nywila + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot - Piga chapa nywila kuwasha mpya + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + - - Enter your password to shut down - Piga chapa nywila kuzima + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + Zima + + + Reboot + Washa upya + + + Suspend + Ahirisha + + + Hibernate + Sinzia fofofo + + + Log out + Aga + + + Are you sure you want to shut down? + Ni kweli unataka kuzima? + + + Are you sure you want to reboot? + Ni kweli unataka kuwasha upya? + + + Are you sure you want to log out? + Ni kweli unataka kuaga? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_ta.ts b/translations/dde-session-shell_ta.ts index f6c20cf9..61e57543 100644 --- a/translations/dde-session-shell_ta.ts +++ b/translations/dde-session-shell_ta.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - நிறுத்து + Verify your fingerprint + - - - - - Reboot - மறுதொடக்கம் + Verification successful + - - - - Suspend - தற்காலிகமாக நிறுத்தம் செய்தல் + + Verification failed, %n chances left + - - - Hibernate + Verification failed, only one chance left - - - - Log out - வெளியேறு + Fingerprint locked, use password please + + + + AuthIris - - Are you sure you want to shut down? + Iris ID - - Are you sure you want to reboot? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to log out? + Verification failed, only one chance left - - Lock - பூட்டு + Verify your Iris ID + - - Switch user - பயனரை மாற்று + Iris ID locked, use password please + - DeepinAuthFramework + AuthPasskey + + Please plug in the security key + + - - Verify your fingerprint or password + Verification successful + + + + Verification failed + + + + Identifying the security key - GreeterWorkek + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password தவறான கடவுச்சொல் - - The domain account or password is not correct. Please enter again. + Password + கடவுச்சொல் + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + தவறான கடவுச்சொல் + + InhibitWarnView - Cancel நிறுத்து + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - தவறான கடவுச்சொல் - MultiUsersWarningView - Cancel நிறுத்து - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down நிறுத்து - - Reboot மறுதொடக்கம் - - Suspend தற்காலிகமாக நிறுத்தம் செய்தல் - - Hibernate + + Lock + பூட்டு + + + Log out + வெளியேறு + + + Switch user + பயனரை மாற்று + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor கணினி கண்காணிப்பு தொடங்கவும் - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 - - New password + 请输入手机号 - - Repeat password + 请输入验证码 - - Failed to change your password + 获取验证码 + + + UpdateWorker - - Password too weak + Update - - Please enter the new password + Please plug in and then install updates. + + + UsersWithTheSameName - - Please repeat the new password + Return - - Passwords do not match + Please select the account for login + + + + Local Account + + + + Domain Account - UserLoginWidget + WarningContent - - Password - கடவுச்சொல் + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + - - Account + To close the program, click Cancel, and then close the program. - - Enter your password to reboot + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Please enter the account + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the password + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - - Please try again %n minute(s) later - + + Shut down + நிறுத்து + + + Reboot + மறுதொடக்கம் + + + Suspend + தற்காலிகமாக நிறுத்தம் செய்தல் + + + Hibernate + + + + Log out + வெளியேறு + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_te.ts b/translations/dde-session-shell_te.ts new file mode 100644 index 00000000..fab69c82 --- /dev/null +++ b/translations/dde-session-shell_te.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_th.ts b/translations/dde-session-shell_th.ts new file mode 100644 index 00000000..88a8e4d4 --- /dev/null +++ b/translations/dde-session-shell_th.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + การตรวจสอบ สําเร็จ + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + การตรวจสอบ สําเร็จ + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + การตรวจสอบ สําเร็จ + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + การตรวจสอบ สําเร็จ + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + รหัสผ่าน + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + การตรวจสอบ สําเร็จ + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + ยกเลิก + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + ยกเลิก + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + ปิดเครื่อง + + + Reboot + รีบูต + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + ปิดเครื่อง + + + Reboot + รีบูต + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_tr.ts b/translations/dde-session-shell_tr.ts index d5be712b..3510d142 100644 --- a/translations/dde-session-shell_tr.ts +++ b/translations/dde-session-shell_tr.ts @@ -27,7 +27,7 @@ Device unavailable! - + Cihaz erişilemez! @@ -80,6 +80,25 @@ İris kimliği kilitli, şifreyi kullanın lütfen + + AuthPasskey + + Please plug in the security key + Lütfen güvenlik anahtarını takın + + + Verification successful + Doğrulama başarılı + + + Verification failed + Doğrulama başarısız oldu + + + Identifying the security key + Güvenlik anahtarının tanımlanması + + AuthPassword @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - Parolanızın süresi %n gün içinde dolacak, lütfen zamanında değiştirin Parolanızın süresi %n gün içinde dolacak, lütfen zamanında değiştirin + Şifreniz %n gün içinde sona erecek, lütfen zamanında değiştirinŞifreniz %n gün içinde sona erecek, lütfen zamanında değiştirin Password expired, please change Parolanın süresi doldu, lütfen değiştir + + Your password has expired. Please contact the administrator to change it + Şifrenizin süresi doldu. Lütfen değiştirmek için yöneticiyle iletişime geçin + + + Terminal locked, please contact administrator + Terminal kilitlendi, lütfen yöneticiyle iletişime geçin + + + + DeepinAuthFramework + + Wrong Password + Yanlış Şifre + GreeterWorker @@ -209,6 +243,17 @@ Cancel İptal + + The reason of inhibit. + Engellemenin sebebi. + + + + LighterGreeter + + Standard Mode + Standart Mod + LockContent @@ -288,6 +333,14 @@ Switch system Sistem değiştir + + Update and Shut Down + Güncelleştir ve Kapat + + + Update and Reboot + Güncelleştir ve Yeniden Başlat + SystemMonitor @@ -296,6 +349,55 @@ Sistem izleyiciyi başlat + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + Güncelle + + + Please plug in and then install updates. + Lütfen fişe takın ve ardından güncellemeleri yükleyin. + + + + UsersWithTheSameName + + Return + Geri dön + + + Please select the account for login + Lütfen giriş yapmak için hesabı seçin + + + Local Account + Yerel Hesap + + + Domain Account + Alan Adı Hesabı + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Oturumu kapatmak istediğinize emin misiniz? + + Update and Shut Down + Güncelleştir ve Kapat + + + Update and Reboot + Güncelleştir ve Yeniden Başlat + + + Closing the programs and shutting down, please wait... + Programlar ve sistem kapatılıyor, lütfen bekleyin... + + + Closing the programs and rebooting, please wait... + Programlar kapatılıp yeniden başlatılıyor, lütfen bekleyin... + + + Closing the programs and logging out, please wait... + Programlar kapatılıp çıkış yapılıyor, lütfen bekleyin... + + + + dss::module::AssistLoginWidget + + Automatic login + Otomatik giriş + dss::module::NetworkModule diff --git a/translations/dde-session-shell_tzm.ts b/translations/dde-session-shell_tzm.ts new file mode 100644 index 00000000..4a0bcef1 --- /dev/null +++ b/translations/dde-session-shell_tzm.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + Taguri n uzray + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Amiḍan + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + Sser + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + Sser + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + Ssexsi + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + Rgel + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + Ssexsi + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + Is nit texsed ad tessexsid? + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_ug.ts b/translations/dde-session-shell_ug.ts index 0da6634b..74ad73f3 100644 --- a/translations/dde-session-shell_ug.ts +++ b/translations/dde-session-shell_ug.ts @@ -23,11 +23,11 @@ Face ID locked, use password please - چىرايدا قۇلۇپ ئېچىش قۇلۇپلىنىپ قالدى، پارولنى كىرگۈزۈپ ئېچىڭ + چىرايدا قۇلۇپ ئېچىش قۇلۇپلىنىپ قالدى، پارولنى كىرگۈزۈڭ Device unavailable! - + ئۈسكۈنىنى ئىشلەتكىلى بولمايدۇ! @@ -50,7 +50,7 @@ Fingerprint locked, use password please - بارماق ئىزى قۇلۇپلاندى، پارول كىرگۈزۈڭ + بارماق ئىزىدا ئېچىش قۇلۇپلىنىپ قالدى، پارولنى كىرگۈزۈڭ @@ -77,7 +77,26 @@ Iris ID locked, use password please - كۆز رەڭدار پەردىسىنى تونۇپ قۇلۇپنى ئېچىش مەغلۇپ بولدى ، پارولنى كىرگۈزۈڭ + كۆز رەڭدار پەردىسىنى تونۇپ قۇلۇپنى ئېچىش قۇلۇپلىنىپ قالدى، پارولنى كىرگۈزۈڭ + + + + AuthPasskey + + Please plug in the security key + بىخەتەرلىك ئاچقۇچىنى كىرگۈزۈڭ + + + Verification successful + دەلىللەندى + + + Verification failed + دەلىللەش مەغلۇپ بولدى + + + Identifying the security key + بىخەتەرلىك ئاچقۇچىنى تونۇۋاتىدۇ @@ -174,7 +193,7 @@ Please try again %n minutes later - %n مىنۇتتىن كېيىن قايتا سىناڭيەنە %n% مىنۇتتىن كېيىن قايتا سىناڭ + %n مىنۇتتىن كېيىن قايتا سىناڭ%n مىنۇتتىن كېيىن قايتا سىناڭ @@ -185,12 +204,27 @@ Your password will expire in %n days, please change it timely - پارولنىڭ ۋاقتى %n كۈندە توشىدۇ، پارولنى ۋاقتىدا ئۆزگەرتىڭپارولنىڭ ۋاقتى %n كۈندە توشىدۇ، پارولنى ۋاقتىدا ئۆزگەرتىڭ + پارولنىڭ ۋاقتى %n كۈندىن كېيىن توشىدۇ، پارولنى ۋاقتىدا ئۆزگەرتىڭپارولنىڭ ۋاقتى %n كۈندىن كېيىن توشىدۇ، پارولنى ۋاقتىدا ئۆزگەرتىڭ Password expired, please change پارولنىڭ ۋاقتى ئۆتتى، ئۆزگەرتىڭ + + Your password has expired. Please contact the administrator to change it + پارولىڭىزنىڭ ۋاقتى ئۆتۈپ كەتتى، باشقۇرغۇچى بىلەن ئالاقىلىشىپ پارول ئۆزگەرتىڭ + + + Terminal locked, please contact administrator + بۇ ئۈسكۈنە قۇلۇپلىنىپ قالدى، باشقۇرغۇچى بىلەن ئالاقىلىشىڭ + + + + DeepinAuthFramework + + Wrong Password + + GreeterWorker @@ -209,16 +243,27 @@ Cancel بىكار قىلىش + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + ئۆلچەملىك ھالەت + LockContent Lock Screen - ئېكران قۇلۇپى + ئېكراننى قۇلۇپلاش Failed to lock screen - ئېكراننى قۇلۇپلانمىدى + ئېكران قۇلۇپلانمىدى @@ -244,7 +289,7 @@ The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - بۇ كومپيۇتېردا يەنە يۇقارقى ھېساباتلار ئوچۇق، قايتا قوزغاتسىڭىز سانلىق مەلۇماتلار يوقاپ كېتىشى مۇمكىن، راستلا قايتا قوزغىتامسىز؟ + بۇ كومپيۇتېردا يەنە يۇقارقى ھېساباتلار ئوچۇق، كومپيۇتېرنى قايتا قوزغاتسىڭىز سانلىق مەلۇماتلار يوقاپ كېتىدۇ، راستلا قايتا قوزغىتامسىز؟ @@ -274,7 +319,7 @@ Lock - قۇلۇپلاش + ئېكران قۇلۇپلاش Log out @@ -288,6 +333,14 @@ Switch system سىستېما ئالماشتۇرۇش + + Update and Shut Down + يېڭىلاش ۋە تاقاش + + + Update and Reboot + يېڭىلاش ۋە قايتا قوزغىتىش + SystemMonitor @@ -296,6 +349,55 @@ سىستېما نازارەتچىسىنى قوزغىتىش + + UdcpMFALoginWidget + + 发送验证码 + دەلىللەش كودى يوللاش + + + 请输入手机号 + يانفون نومۇرىڭىزنى كىرگۈزۈڭ + + + 请输入验证码 + دەلىللەش كودىنى كىرگۈزۈڭ + + + 获取验证码 + دەلىللەش كودىغا ئېرىشىش + + + + UpdateWorker + + Update + يېڭىلاش + + + Please plug in and then install updates. + توكقا چېتىپ ئاندىن يېڭىلاڭ + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? راستلا چېكىنەمسىز؟ + + Update and Shut Down + يېڭىلاش ۋە تاقاش + + + Update and Reboot + يېڭىلاش ۋە قايتا قوزغىتىش + + + Closing the programs and shutting down, please wait... + يۇقىرىقى پىروگراممىلارنى تاقاپ ئۆچۈۋاتىدۇ، سەل ساقلاڭ... + + + Closing the programs and rebooting, please wait... + يۇقىرىقى پىروگراممىلارنى تاقاپ قايتا قوزغىلىۋاتىدۇ، سەل ساقلاڭ... + + + Closing the programs and logging out, please wait... + يۇقىرىقى پىروگراممىلارنى تاقاپ چېكىنىۋاتىدۇ، سەل ساقلاڭ... + + + + dss::module::AssistLoginWidget + + Automatic login + + dss::module::NetworkModule diff --git a/translations/dde-session-shell_uk.ts b/translations/dde-session-shell_uk.ts index 2377e668..a807a048 100644 --- a/translations/dde-session-shell_uk.ts +++ b/translations/dde-session-shell_uk.ts @@ -27,7 +27,7 @@ Device unavailable! - + Пристрій не доступний! @@ -80,6 +80,25 @@ Ідентифікатор райдужки заблоковано. Скористайтеся, будь ласка, паролем + + AuthPasskey + + Please plug in the security key + Будь ласка, вставте ключ захисту + + + Verification successful + Перевірку пройдено + + + Verification failed + Перевірку не пройдено + + + Identifying the security key + Ідентифікуємо ключ захисту + + AuthPassword @@ -191,6 +210,21 @@ Password expired, please change Строк дії пароля вичерпано. Будь ласка, змініть + + Your password has expired. Please contact the administrator to change it + Строк дії пароля вичерпано. Будь ласка, зв'яжіться з адміністратором, щоб змінити його. + + + Terminal locked, please contact administrator + Термінал заблоковано, будь ласка, зв'яжіться з адміністратором + + + + DeepinAuthFramework + + Wrong Password + Помилковий пароль + GreeterWorker @@ -209,6 +243,17 @@ Cancel Скасувати + + The reason of inhibit. + Причина заборони. + + + + LighterGreeter + + Standard Mode + Стандартний режим + LockContent @@ -288,6 +333,14 @@ Switch system Перемкнути систему + + Update and Shut Down + Оновити і вимкнути + + + Update and Reboot + Оновити і перезавантажити + SystemMonitor @@ -296,6 +349,55 @@ Запустити системний монітор + + UdcpMFALoginWidget + + 发送验证码 + Введіть код підтвердження + + + 请输入手机号 + Будь ласка, введіть номер телефону + + + 请输入验证码 + Будь ласка, введіть код підтвердження + + + 获取验证码 + Отримати код підтвердження + + + + UpdateWorker + + Update + Оновлення + + + Please plug in and then install updates. + Будь ласка, з'єднайте комп'ютер з джерелом живлення, потім встановлюйте оновлення. + + + + UsersWithTheSameName + + Return + Повернутися + + + Please select the account for login + Будь ласка, виберіть обліковий запис для входу + + + Local Account + Локальний обліковий запис + + + Domain Account + Доменний обліковий запис + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? Ви впевнені, що хочете вийти? + + Update and Shut Down + Оновити і вимкнути + + + Update and Reboot + Оновити і перезавантажити + + + Closing the programs and shutting down, please wait... + Завершуємо роботу програм і вимикаємо комп'ютер, зачекайте… + + + Closing the programs and rebooting, please wait... + Завершуємо роботу програм і перезавантажуємо систему, зачекайте… + + + Closing the programs and logging out, please wait... + Завершуємо роботу програм і виходимо із системи, зачекайте… + + + + dss::module::AssistLoginWidget + + Automatic login + Автоматичний вхід + dss::module::NetworkModule diff --git a/translations/dde-session-shell_ur.ts b/translations/dde-session-shell_ur.ts index d0ad3dac..9876256e 100644 --- a/translations/dde-session-shell_ur.ts +++ b/translations/dde-session-shell_ur.ts @@ -1,139 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Face ID - - - - - - To close the program, click Cancel, and then close the program. + Verification successful + + Verification failed, %n chances left + + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Verification failed, only one chance left - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Verify your Face ID - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Face ID locked, use password please - - The programs are preventing the computer from log out, and forcing log out may cause data loss. + Device unavailable! + + + AuthFingerprint - - - - - Shut down - شٹڈاون + Verify your fingerprint + - - - - - Reboot + Verification successful + + Verification failed, %n chances left + + - - - Suspend + Verification failed, only one chance left - - - Hibernate + Fingerprint locked, use password please + + + AuthIris - - - - Log out + Iris ID - - Are you sure you want to shut down? + Verification successful + + Verification failed, %n chances left + + - - Are you sure you want to reboot? + Verification failed, only one chance left - - Are you sure you want to log out? + Verify your Iris ID - - Lock + Iris ID locked, use password please + + + AuthPasskey - - Switch user + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key - DeepinAuthFramework + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + - - Verify your fingerprint or password + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? - GreeterWorkek + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework - Wrong Password + + + GreeterWorker - - The domain account or password is not correct. Please enter again. + Wrong account + + + + Wrong Password InhibitWarnView - Cancel + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen - Failed to lock screen @@ -141,157 +269,230 @@ LockWorker - - Domain account - - - - Fingerprint verification timed out, please enter your password manually - Failed to match fingerprint - - - Wrong Password - - MultiUsersWarningView - Cancel - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down شٹڈاون - - Reboot - - Suspend - - Hibernate + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change + 发送验证码 + + + + 请输入手机号 - - New password + 请输入验证码 - - Repeat password + 获取验证码 + + + + + UpdateWorker + + Update - - Failed to change your password + Please plug in and then install updates. + + + UsersWithTheSameName - - Password too weak + Return - - Please enter the new password + Please select the account for login - - Please repeat the new password + Local Account - - Passwords do not match + Domain Account - UserLoginWidget + WarningContent - - Password + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - - Account + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - - Enter your password to reboot + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - - Enter your password to shut down + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - - Please enter the account + The programs are preventing the computer from log out, and forcing log out may cause data loss. - - Please enter the password + Shut down + شٹڈاون + + + Reboot - - - Please try again %n minute(s) later - + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + \ No newline at end of file diff --git a/translations/dde-session-shell_uz.ts b/translations/dde-session-shell_uz.ts new file mode 100644 index 00000000..b9e850b0 --- /dev/null +++ b/translations/dde-session-shell_uz.ts @@ -0,0 +1,498 @@ + + + AuthFace + + Face ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Face ID + + + + Face ID locked, use password please + + + + Device unavailable! + + + + + AuthFingerprint + + Verify your fingerprint + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Fingerprint locked, use password please + + + + + AuthIris + + Iris ID + + + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Verify your Iris ID + + + + Iris ID locked, use password please + + + + + AuthPasskey + + Please plug in the security key + + + + Verification successful + + + + Verification failed + + + + Identifying the security key + + + + + AuthPassword + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong Password + + + + Password + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + + + + + InhibitWarnView + + Cancel + Bekor qilish + + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + + + + LockContent + + Lock Screen + + + + Failed to lock screen + + + + + LockWorker + + Fingerprint verification timed out, please enter your password manually + + + + Failed to match fingerprint + + + + + MultiUsersWarningView + + Cancel + Bekor qilish + + + The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? + + + + The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? + + + + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + + + ShutdownWidget + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Lock + + + + Log out + + + + Switch user + + + + Switch system + + + + Update and Shut Down + + + + Update and Reboot + + + + + SystemMonitor + + Start system monitor + + + + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + + + + Please plug in and then install updates. + + + + + UsersWithTheSameName + + Return + + + + Please select the account for login + + + + Local Account + + + + Domain Account + + + + + WarningContent + + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + + + + To close the program, click Cancel, and then close the program. + + + + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + + + + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + + + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + + + + Shut down + + + + Reboot + + + + Suspend + + + + Hibernate + + + + Log out + + + + Are you sure you want to shut down? + + + + Are you sure you want to reboot? + + + + Are you sure you want to log out? + + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + + + + Turn off + + + + \ No newline at end of file diff --git a/translations/dde-session-shell_vi.ts b/translations/dde-session-shell_vi.ts index 69b84865..46bbe1f5 100644 --- a/translations/dde-session-shell_vi.ts +++ b/translations/dde-session-shell_vi.ts @@ -1,136 +1,267 @@ - + - ContentWidget + AuthFace - - The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. - Các chương trình đang ngăn máy tính tắt và buộc tắt máy có thể gây mất dữ liệu. + Face ID + - - - - - - To close the program, click Cancel, and then close the program. - Để đóng chương trình, bấm Hủy, rồi đóng chương trình. + Verification successful + Xác minh thành công + + + Verification failed, %n chances left + - - The programs are preventing the computer from reboot, and forcing reboot may cause data loss. - Các chương trình đang ngăn máy tính khởi động lại và buộc khởi động lại có thể gây mất dữ liệu. + Verification failed, only one chance left + - - The programs are preventing the computer from suspend, and forcing suspend may cause data loss. - Các chương trình đang ngăn máy tính tạm ngưng và buộc tạm dừng có thể gây mất dữ liệu. + Verify your Face ID + - - The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. - Các chương trình đang ngăn máy tính ngủ đông và buộc ngủ đông có thể gây mất dữ liệu. + Face ID locked, use password please + - - The programs are preventing the computer from log out, and forcing log out may cause data loss. - Các chương trình đang ngăn máy tính đăng xuất và buộc đăng xuất có thể gây mất dữ liệu. + Device unavailable! + + + + AuthFingerprint - - - - - Shut down - Tắt máy + Verify your fingerprint + - - - - - Reboot - Khởi động lại + Verification successful + Xác minh thành công + + + Verification failed, %n chances left + - - - Suspend - Dừng + Verification failed, only one chance left + - - - Hibernate - Ngủ đông + Fingerprint locked, use password please + Vân tay bị khóa, xin vui lòng sử dụng mật khẩu + + + AuthIris - - - - Log out - Thoát ra + Iris ID + - - Are you sure you want to shut down? - Bạn có chắc chắn muốn tắt máy? + Verification successful + Xác minh thành công + + + Verification failed, %n chances left + - - Are you sure you want to reboot? - Bạn có chắc chắn muốn khởi động lại? + Verification failed, only one chance left + - - Are you sure you want to log out? - Bạn có chắc chắn bạn muốn thoát? + Verify your Iris ID + - - Lock - Khóa + Iris ID locked, use password please + + + + AuthPasskey - - Switch user - Đổi người dùng + Please plug in the security key + - - Switch system - Chuyển đổi hệ thống + Verification successful + + + + Verification failed + + + + Identifying the security key + - GreeterWorkek + AuthPassword + + Verification successful + Xác minh thành công + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + - Wrong Password Sai Mật mã - - The account or password is not correct. Please enter again. - Tài khoản hoặc mật khẩu không đúng, vui lòng thử lại. + Password + Mật mã + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthSingle + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + Reset Password + + + + Forgot password? + + + + + AuthUKey + + Verification successful + Xác minh thành công + + + Verification failed, %n chances left + + + + Verification failed, only one chance left + + + + Wrong PIN + + + + UKey is required + + + + Enter your PIN + + + + Please try again %n minute(s) later + + + + Please try again 1 minute later + + + + Please try again %n minutes later + + + + + AuthWidget + + Account + Tài khoản + + + Your password will expire in %n days, please change it timely + + + + Password expired, please change + Mật khẩu đã hết hạn, vui lòng thay đổi + + + Your password has expired. Please contact the administrator to change it + + + + Terminal locked, please contact administrator + + + + + DeepinAuthFramework + + Wrong Password + + + + + GreeterWorker + + Wrong account + + + + Wrong Password + Sai Mật mã InhibitWarnView - Cancel Hủy + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + + LockContent - Lock Screen Khóa màn hình - Failed to lock screen Lỗi khi khóa màn hình @@ -138,142 +269,230 @@ LockWorker - Fingerprint verification timed out, please enter your password manually Đã hết thời gian xác minh vân tay, vui lòng nhập mật khẩu của bạn theo cách thủ công - Failed to match fingerprint Dấu vân tay không khớp - - - Wrong Password - Sai Mật mã - MultiUsersWarningView - Cancel Hủy - The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? Những người dùng trên vẫn đăng nhập và dữ liệu sẽ bị mất do tắt máy, bạn có chắc chắn muốn tắt không? - The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? Những người dùng trên vẫn đăng nhập và dữ liệu sẽ bị mất do khởi động lại, bạn có chắc chắn muốn khởi động lại không? + + SessionWidget + + You have enabled the high system security level, thus cannot switch to the Wayland mode, please disable the high security level in Security Center and try again. + + + ShutdownWidget - Shut down Tắt máy - - Reboot Khởi động lại - - Suspend Dừng - - Hibernate Ngủ đông + + Lock + Khóa + + + Log out + Thoát ra + + + Switch user + Đổi người dùng + + + Switch system + Chuyển đổi hệ thống + + + Update and Shut Down + + + + Update and Reboot + + SystemMonitor - Start system monitor Khởi động system monitor - UserExpiredWidget + UdcpMFALoginWidget - - Password expired, please change - Mật khẩu đã hết hạn, vui lòng thay đổi + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + - - New password - Mật khẩu mới + 获取验证码 + + + + UpdateWorker - - Repeat password - Lặp lại mật mã + Update + - - Failed to change your password - Không thể thay đổi mật khẩu của bạn + Please plug in and then install updates. + + + + UsersWithTheSameName - - Password too weak - Mật khẩu quá yếu + Return + - - Please enter the new password - Vui lòng nhập mật khẩu mới + Please select the account for login + - - Please repeat the new password - Vui lòng xác nhận lại mật khẩu mới + Local Account + - - Passwords do not match - Mật khẩu không phù hợp + Domain Account + - UserLoginWidget + WarningContent - - Password - Mật mã + The programs are preventing the computer from shutting down, and forcing shut down may cause data loss. + Các chương trình đang ngăn máy tính tắt và buộc tắt máy có thể gây mất dữ liệu. - - Account - Tài khoản + To close the program, click Cancel, and then close the program. + Để đóng chương trình, bấm Hủy, rồi đóng chương trình. - - Please enter the account - Vui lòng nhập tài khoản + The programs are preventing the computer from reboot, and forcing reboot may cause data loss. + Các chương trình đang ngăn máy tính khởi động lại và buộc khởi động lại có thể gây mất dữ liệu. - - Please enter the password - Vui lòng nhập mật khẩu + The programs are preventing the computer from suspend, and forcing suspend may cause data loss. + Các chương trình đang ngăn máy tính tạm ngưng và buộc tạm dừng có thể gây mất dữ liệu. - - - Please try again %n minute(s) later - + + The programs are preventing the computer from hibernate, and forcing hibernate may cause data loss. + Các chương trình đang ngăn máy tính ngủ đông và buộc ngủ đông có thể gây mất dữ liệu. + + + The programs are preventing the computer from log out, and forcing log out may cause data loss. + Các chương trình đang ngăn máy tính đăng xuất và buộc đăng xuất có thể gây mất dữ liệu. + + + Shut down + Tắt máy + + + Reboot + Khởi động lại + + + Suspend + Dừng + + + Hibernate + Ngủ đông + + + Log out + Thoát ra + + + Are you sure you want to shut down? + Bạn có chắc chắn muốn tắt máy? + + + Are you sure you want to reboot? + Bạn có chắc chắn muốn khởi động lại? + + + Are you sure you want to log out? + Bạn có chắc chắn bạn muốn thoát? + + + Update and Shut Down + + + + Update and Reboot + + + + Closing the programs and shutting down, please wait... + + + + Closing the programs and rebooting, please wait... + + + + Closing the programs and logging out, please wait... + + + + + dss::module::AssistLoginWidget + + Automatic login + + + + + dss::module::NetworkModule + + Turn on + Mở + + + Turn off + Tắt \ No newline at end of file diff --git a/translations/dde-session-shell_zh_CN.ts b/translations/dde-session-shell_zh_CN.ts index 155173c1..6f6070e8 100644 --- a/translations/dde-session-shell_zh_CN.ts +++ b/translations/dde-session-shell_zh_CN.ts @@ -80,6 +80,25 @@ 虹膜ID已锁定,请输入密码 + + AuthPasskey + + Please plug in the security key + 请插入安全密钥 + + + Verification successful + 验证成功 + + + Verification failed + 验证失败 + + + Identifying the security key + 正在识别安全密钥 + + AuthPassword @@ -181,7 +200,7 @@ AuthWidget Account - 帐户 + 账户 Your password will expire in %n days, please change it timely @@ -191,12 +210,27 @@ Password expired, please change 密码已过期,请修改 + + Your password has expired. Please contact the administrator to change it + 您的密码已过期,请联系管理员修改密码 + + + Terminal locked, please contact administrator + 该设备已被锁定,请联系管理员 + + + + DeepinAuthFramework + + Wrong Password + 密码错误 + GreeterWorker Wrong account - 帐户错误 + 账户错误 Wrong Password @@ -209,6 +243,17 @@ Cancel 取消 + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + 标准模式 + LockContent @@ -240,11 +285,11 @@ The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - 此电脑还有以上帐户在登录,关闭电脑会导致其数据丢失,是否要关闭此电脑? + 此电脑还有以上账户在登录,关闭电脑会导致其数据丢失,是否要关闭此电脑? The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - 此电脑还有以上帐户在登录,重启电脑会导致其数据丢失,是否要重启此电脑? + 此电脑还有以上账户在登录,重启电脑会导致其数据丢失,是否要重启此电脑? @@ -274,7 +319,7 @@ Lock - 锁定 + 锁屏 Log out @@ -288,6 +333,14 @@ Switch system 切换系统 + + Update and Shut Down + 更新并关机 + + + Update and Reboot + 更新并重启 + SystemMonitor @@ -296,6 +349,55 @@ 启动系统监视器 + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + 更新 + + + Please plug in and then install updates. + 请插入电源后再开始更新 + + + + UsersWithTheSameName + + Return + 返回 + + + Please select the account for login + 请选择登录的账户 + + + Local Account + 本地账户 + + + Domain Account + 域账户 + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? 您确定要注销吗? + + Update and Shut Down + 更新并关机 + + + Update and Reboot + 更新并重启 + + + Closing the programs and shutting down, please wait... + 正在关闭以上程序并关机,请稍后... + + + Closing the programs and rebooting, please wait... + 正在关闭以上程序并重启,请稍后... + + + Closing the programs and logging out, please wait... + 正在关闭以上程序并注销,请稍后... + + + + dss::module::AssistLoginWidget + + Automatic login + 自动登录 + dss::module::NetworkModule diff --git a/translations/dde-session-shell_zh_HK.ts b/translations/dde-session-shell_zh_HK.ts index 1f5cae80..1eabb346 100644 --- a/translations/dde-session-shell_zh_HK.ts +++ b/translations/dde-session-shell_zh_HK.ts @@ -80,6 +80,25 @@ 虹膜ID已鎖定,請輸入密碼 + + AuthPasskey + + Please plug in the security key + 請插入安全密鑰 + + + Verification successful + 驗證成功 + + + Verification failed + 驗證失敗 + + + Identifying the security key + 正在識別安全密鑰 + + AuthPassword @@ -181,7 +200,7 @@ AuthWidget Account - 帳戶 + 賬戶 Your password will expire in %n days, please change it timely @@ -191,12 +210,27 @@ Password expired, please change 密碼已過期,請修改 + + Your password has expired. Please contact the administrator to change it + 您的密碼已過期,請聯繫管理員修改密碼 + + + Terminal locked, please contact administrator + 該設備已被鎖定,請聯繫管理員 + + + + DeepinAuthFramework + + Wrong Password + 密碼錯誤 + GreeterWorker Wrong account - 帳戶錯誤 + 賬戶錯誤 Wrong Password @@ -209,6 +243,17 @@ Cancel 取消 + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + 標準模式 + LockContent @@ -240,11 +285,11 @@ The above users are still logged in and data will be lost due to shutdown, are you sure you want to shut down? - 此電腦還有以上帳戶在登錄,關閉電腦會導致其數據丟失,是否要關閉此電腦? + 此電腦還有以上賬戶在登錄,關閉電腦會導致其數據丟失,是否要關閉此電腦? The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - 此電腦還有以上帳戶在登錄,重啟電腦會導致其數據丟失,是否要重啟此電腦? + 此電腦還有以上賬戶在登錄,重啟電腦會導致其數據丟失,是否要重啟此電腦? @@ -274,11 +319,11 @@ Lock - 鎖定 + 鎖定螢幕 Log out - 註銷 + 登出 Switch user @@ -288,6 +333,14 @@ Switch system 切換系統 + + Update and Shut Down + 更新並關機 + + + Update and Reboot + 更新並重啟 + SystemMonitor @@ -296,6 +349,55 @@ 啟動系統監視器 + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + 更新 + + + Please plug in and then install updates. + 請插入電源後再開始更新 + + + + UsersWithTheSameName + + Return + 返回 + + + Please select the account for login + 請選擇登錄的賬戶 + + + Local Account + 本地賬戶 + + + Domain Account + 域賬戶 + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? 您確定要註銷嗎? + + Update and Shut Down + 更新並關機 + + + Update and Reboot + 更新並重啟 + + + Closing the programs and shutting down, please wait... + 正在關閉以上程序並關機,請稍後... + + + Closing the programs and rebooting, please wait... + 正在關閉以上程序並重啟,請稍後... + + + Closing the programs and logging out, please wait... + 正在關閉以上程序並註銷,請稍後... + + + + dss::module::AssistLoginWidget + + Automatic login + 自動登錄 + dss::module::NetworkModule diff --git a/translations/dde-session-shell_zh_TW.ts b/translations/dde-session-shell_zh_TW.ts index b872767e..51dcab92 100644 --- a/translations/dde-session-shell_zh_TW.ts +++ b/translations/dde-session-shell_zh_TW.ts @@ -80,6 +80,25 @@ 虹膜ID已鎖定,請輸入密碼 + + AuthPasskey + + Please plug in the security key + 請插入安全金鑰 + + + Verification successful + 驗證成功 + + + Verification failed + 驗證失敗 + + + Identifying the security key + 正在識別安全金鑰 + + AuthPassword @@ -191,6 +210,21 @@ Password expired, please change 密碼已過期,請修改 + + Your password has expired. Please contact the administrator to change it + 您的密碼已過期,請聯絡管理員修改密碼 + + + Terminal locked, please contact administrator + 該裝置已被鎖定,請聯絡管理員 + + + + DeepinAuthFramework + + Wrong Password + 密碼錯誤 + GreeterWorker @@ -209,6 +243,17 @@ Cancel 取消 + + The reason of inhibit. + + + + + LighterGreeter + + Standard Mode + 標準模式 + LockContent @@ -244,7 +289,7 @@ The above users are still logged in and data will be lost due to reboot, are you sure you want to reboot? - 以上的使用者仍在登入,且重開機後這些使用者的資料將會遺失。確定重啟? + 此電腦還有以上帳戶在登入,重啟電腦會導致其資料遺失,是否要重啟此電腦? @@ -274,7 +319,7 @@ Lock - 鎖定 + 鎖定螢幕 Log out @@ -288,6 +333,14 @@ Switch system 切換系統 + + Update and Shut Down + 更新並關機 + + + Update and Reboot + 更新並重啟 + SystemMonitor @@ -296,6 +349,55 @@ 啟動系統監視器 + + UdcpMFALoginWidget + + 发送验证码 + + + + 请输入手机号 + + + + 请输入验证码 + + + + 获取验证码 + + + + + UpdateWorker + + Update + 更新 + + + Please plug in and then install updates. + 請插入電源後再開始更新 + + + + UsersWithTheSameName + + Return + 返回 + + + Please select the account for login + 請選擇登入的帳戶 + + + Local Account + 本機帳戶 + + + Domain Account + 域帳戶 + + WarningContent @@ -354,6 +456,33 @@ Are you sure you want to log out? 確定登出? + + Update and Shut Down + 更新並關機 + + + Update and Reboot + 更新並重啟 + + + Closing the programs and shutting down, please wait... + 正在關閉以上程式並關機,請稍後... + + + Closing the programs and rebooting, please wait... + 正在關閉以上程式並重啟,請稍後... + + + Closing the programs and logging out, please wait... + 正在關閉以上程式並註銷,請稍後... + + + + dss::module::AssistLoginWidget + + Automatic login + 自動登入 + dss::module::NetworkModule diff --git a/xml/com.deepin.dde.session-shell.gschema.xml b/xml/com.deepin.dde.session-shell.gschema.xml index 6e843c24..541c6d8b 100644 --- a/xml/com.deepin.dde.session-shell.gschema.xml +++ b/xml/com.deepin.dde.session-shell.gschema.xml @@ -72,5 +72,15 @@ delaytime + + false + check password before beboot or shutdown + default is false + + + 'Enabled' + change system reboot status + default is Enabled + diff --git a/xml/snipe/com.deepin.wm.xml b/xml/snipe/com.deepin.wm.xml new file mode 100644 index 00000000..d42bf237 --- /dev/null +++ b/xml/snipe/com.deepin.wm.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.Accounts1.User.xml b/xml/snipe/org.deepin.dde.Accounts1.User.xml new file mode 100644 index 00000000..bad69f6a --- /dev/null +++ b/xml/snipe/org.deepin.dde.Accounts1.User.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.Accounts1.xml b/xml/snipe/org.deepin.dde.Accounts1.xml new file mode 100644 index 00000000..27f88ee5 --- /dev/null +++ b/xml/snipe/org.deepin.dde.Accounts1.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.Authenticate1.Session2.xml b/xml/snipe/org.deepin.dde.Authenticate1.Session2.xml new file mode 100755 index 00000000..27081171 --- /dev/null +++ b/xml/snipe/org.deepin.dde.Authenticate1.Session2.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.Authenticate1.xml b/xml/snipe/org.deepin.dde.Authenticate1.xml new file mode 100644 index 00000000..de9c34f4 --- /dev/null +++ b/xml/snipe/org.deepin.dde.Authenticate1.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.ImageEffect1.xml b/xml/snipe/org.deepin.dde.ImageEffect1.xml new file mode 100644 index 00000000..819bcf08 --- /dev/null +++ b/xml/snipe/org.deepin.dde.ImageEffect1.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.Logined.xml b/xml/snipe/org.deepin.dde.Logined.xml new file mode 100644 index 00000000..4e7662d0 --- /dev/null +++ b/xml/snipe/org.deepin.dde.Logined.xml @@ -0,0 +1,4 @@ + + + + diff --git a/xml/snipe/org.deepin.dde.SessionManager1.xml b/xml/snipe/org.deepin.dde.SessionManager1.xml new file mode 100644 index 00000000..d2b2c134 --- /dev/null +++ b/xml/snipe/org.deepin.dde.SessionManager1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.SystemDisplay1.xml b/xml/snipe/org.deepin.dde.SystemDisplay1.xml new file mode 100644 index 00000000..e26fc482 --- /dev/null +++ b/xml/snipe/org.deepin.dde.SystemDisplay1.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/xml/snipe/org.deepin.dde.SystemPower1.xml b/xml/snipe/org.deepin.dde.SystemPower1.xml new file mode 100644 index 00000000..3e2e3396 --- /dev/null +++ b/xml/snipe/org.deepin.dde.SystemPower1.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/snipe/org.freedesktop.DBus.xml b/xml/snipe/org.freedesktop.DBus.xml new file mode 100644 index 00000000..16487ad7 --- /dev/null +++ b/xml/snipe/org.freedesktop.DBus.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/xml/snipe/org.freedesktop.login1.session.self.xml b/xml/snipe/org.freedesktop.login1.session.self.xml new file mode 100644 index 00000000..cc7f0d15 --- /dev/null +++ b/xml/snipe/org.freedesktop.login1.session.self.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + +